5#include <qpa/qplatformvulkaninstance.h>
7#define VMA_IMPLEMENTATION
8#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
9#define VMA_STATIC_VULKAN_FUNCTIONS 0
10#define VMA_RECORDING_ENABLED 0
11#define VMA_DEDICATED_ALLOCATION 0
13#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
17#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 1100
20#include "vk_mem_alloc.h"
24#include <QVulkanFunctions>
25#include <QtGui/qwindow.h>
289 return (
v + byteAlign - 1) & ~(byteAlign - 1);
306 return reinterpret_cast<VmaAllocation
>(
a);
311 return reinterpret_cast<VmaAllocator
>(
a);
333QByteArrayList QRhiVulkanInitParams::preferredExtensionsForImportedDevice()
351 physDev = importParams->physDev;
352 dev = importParams->dev;
358 if (importParams->vmemAllocator) {
367 QVulkanInstance::DebugMessageTypeFlags
type,
368 const void *callbackData)
372#ifdef VK_EXT_debug_utils
373 const VkDebugUtilsMessengerCallbackDataEXT *
d =
static_cast<const VkDebugUtilsMessengerCallbackDataEXT *
>(callbackData);
377 if (strstr(
d->pMessage,
"Mapping an image with layout")
378 && strstr(
d->pMessage,
"can result in undefined behavior if this memory is used by the device"))
389 if (strstr(
d->pMessage,
"VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307"))
400 case VK_PHYSICAL_DEVICE_TYPE_OTHER:
402 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
404 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
406 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
408 case VK_PHYSICAL_DEVICE_TYPE_CPU:
418 if (!
inst->isValid()) {
419 qWarning(
"Vulkan instance is not valid");
424 qCDebug(QRHI_LOG_INFO,
"Initializing QRhi Vulkan backend %p with flags %d",
this,
int(
rhiFlags));
427 f =
inst->functions();
429 qCDebug(QRHI_LOG_INFO,
"Enabled instance extensions:");
430 for (
const char *ext :
inst->extensions())
431 qCDebug(QRHI_LOG_INFO,
" %s", ext);
437 QList<VkQueueFamilyProperties> queueFamilyProps;
438 auto queryQueueFamilyProps = [
this, &queueFamilyProps] {
439 uint32_t queueCount = 0;
440 f->vkGetPhysicalDeviceQueueFamilyProperties(
physDev, &queueCount,
nullptr);
441 queueFamilyProps.resize(
int(queueCount));
442 f->vkGetPhysicalDeviceQueueFamilyProperties(
physDev, &queueCount, queueFamilyProps.data());
447 uint32_t physDevCount = 0;
448 f->vkEnumeratePhysicalDevices(
inst->vkInstance(), &physDevCount,
nullptr);
453 QVarLengthArray<VkPhysicalDevice, 4> physDevs(physDevCount);
454 VkResult err =
f->vkEnumeratePhysicalDevices(
inst->vkInstance(), &physDevCount, physDevs.data());
455 if (err != VK_SUCCESS || !physDevCount) {
456 qWarning(
"Failed to enumerate physical devices: %d", err);
460 int physDevIndex = -1;
461 int requestedPhysDevIndex = -1;
466 for (
int i = 0;
i < int(physDevCount); ++
i) {
469 requestedPhysDevIndex =
i;
475 for (
int i = 0;
i < int(physDevCount); ++
i) {
477 qCDebug(QRHI_LOG_INFO,
"Physical device %d: '%s' %d.%d.%d (api %d.%d.%d vendor 0x%X device 0x%X type %d)",
489 if (physDevIndex < 0 && (requestedPhysDevIndex < 0 || requestedPhysDevIndex ==
int(
i))) {
491 qCDebug(QRHI_LOG_INFO,
" using this physical device");
495 if (physDevIndex < 0) {
496 qWarning(
"No matching physical device");
499 physDev = physDevs[physDevIndex];
503 qCDebug(QRHI_LOG_INFO,
"Using imported physical device '%s' %d.%d.%d (api %d.%d.%d vendor 0x%X device 0x%X type %d)",
516 caps.apiVersion =
inst->apiVersion();
524 if (physDevApiVersion <
caps.apiVersion) {
525 qCDebug(QRHI_LOG_INFO) <<
"Instance has api version" <<
caps.apiVersion
526 <<
"whereas the chosen physical device has" << physDevApiVersion
527 <<
"- restricting to the latter";
528 caps.apiVersion = physDevApiVersion;
536 bool featuresQueried =
false;
538 VkPhysicalDeviceFeatures2 physDevFeaturesChainable = {};
539 physDevFeaturesChainable.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
544 if (!featuresQueried) {
547 physDevFeatures11IfApi12OrNewer = {};
548 physDevFeatures11IfApi12OrNewer.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
549 physDevFeatures12 = {};
550 physDevFeatures12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
552 physDevFeatures13 = {};
553 physDevFeatures13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
555 physDevFeaturesChainable.pNext = &physDevFeatures11IfApi12OrNewer;
556 physDevFeatures11IfApi12OrNewer.pNext = &physDevFeatures12;
559 physDevFeatures12.pNext = &physDevFeatures13;
561 f->vkGetPhysicalDeviceFeatures2(
physDev, &physDevFeaturesChainable);
562 memcpy(&
physDevFeatures, &physDevFeaturesChainable.features,
sizeof(VkPhysicalDeviceFeatures));
563 featuresQueried =
true;
570 if (!featuresQueried) {
579 multiviewFeaturesIfApi11 = {};
580 multiviewFeaturesIfApi11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
581 physDevFeaturesChainable.pNext = &multiviewFeaturesIfApi11;
582 f->vkGetPhysicalDeviceFeatures2(
physDev, &physDevFeaturesChainable);
583 memcpy(&
physDevFeatures, &physDevFeaturesChainable.features,
sizeof(VkPhysicalDeviceFeatures));
584 featuresQueried =
true;
589 if (!featuresQueried) {
593 featuresQueried =
true;
601 std::optional<uint32_t> gfxQueueFamilyIdxOpt;
602 std::optional<uint32_t> computelessGfxQueueCandidateIdxOpt;
603 queryQueueFamilyProps();
604 const uint32_t queueFamilyCount = uint32_t(queueFamilyProps.size());
605 for (uint32_t
i = 0;
i < queueFamilyCount; ++
i) {
606 qCDebug(QRHI_LOG_INFO,
"queue family %u: flags=0x%x count=%u",
607 i, queueFamilyProps[
i].queueFlags, queueFamilyProps[
i].queueCount);
608 if (!gfxQueueFamilyIdxOpt.has_value()
609 && (queueFamilyProps[
i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
612 if (queueFamilyProps[
i].queueFlags & VK_QUEUE_COMPUTE_BIT)
613 gfxQueueFamilyIdxOpt =
i;
614 else if (!computelessGfxQueueCandidateIdxOpt.has_value())
615 computelessGfxQueueCandidateIdxOpt =
i;
618 if (gfxQueueFamilyIdxOpt.has_value()) {
621 if (computelessGfxQueueCandidateIdxOpt.has_value()) {
624 qWarning(
"No graphics (or no graphics+present) queue family found");
629 VkDeviceQueueCreateInfo queueInfo = {};
630 const float prio[] = { 0 };
631 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
633 queueInfo.queueCount = 1;
634 queueInfo.pQueuePriorities = prio;
636 QList<const char *> devLayers;
637 if (
inst->layers().contains(
"VK_LAYER_KHRONOS_validation"))
638 devLayers.append(
"VK_LAYER_KHRONOS_validation");
640 QVulkanInfoVector<QVulkanExtension> devExts;
641 uint32_t devExtCount = 0;
642 f->vkEnumerateDeviceExtensionProperties(
physDev,
nullptr, &devExtCount,
nullptr);
644 QList<VkExtensionProperties> extProps(devExtCount);
645 f->vkEnumerateDeviceExtensionProperties(
physDev,
nullptr, &devExtCount, extProps.data());
646 for (
const VkExtensionProperties &
p : std::as_const(extProps))
647 devExts.append({
p.extensionName,
p.specVersion });
649 qCDebug(QRHI_LOG_INFO,
"%d device extensions available",
int(devExts.size()));
651 QList<const char *> requestedDevExts;
652 requestedDevExts.append(
"VK_KHR_swapchain");
654 const bool hasPhysDevProp2 =
inst->extensions().contains(
QByteArrayLiteral(
"VK_KHR_get_physical_device_properties2"));
657 if (hasPhysDevProp2) {
658 requestedDevExts.append(
"VK_KHR_portability_subset");
660 qWarning(
"VK_KHR_portability_subset should be enabled on the device "
661 "but the instance does not have VK_KHR_get_physical_device_properties2 enabled. "
666#ifdef VK_EXT_vertex_attribute_divisor
667 if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
668 if (hasPhysDevProp2) {
669 requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
670 caps.vertexAttribDivisor =
true;
675#ifdef VK_KHR_create_renderpass2
676 if (devExts.contains(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) {
677 requestedDevExts.append(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
678 caps.renderPass2KHR =
true;
682#ifdef VK_KHR_depth_stencil_resolve
683 if (devExts.contains(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME)) {
684 requestedDevExts.append(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
685 caps.depthStencilResolveKHR =
true;
690 if (!ext.isEmpty() && !requestedDevExts.contains(ext)) {
691 if (devExts.contains(ext)) {
692 requestedDevExts.append(ext.constData());
694 qWarning(
"Device extension %s requested in QRhiVulkanInitParams is not supported",
702 if (!ext.isEmpty() && !requestedDevExts.contains(ext)) {
703 if (devExts.contains(ext)) {
704 requestedDevExts.append(ext.constData());
706 qWarning(
"Device extension %s requested in QT_VULKAN_DEVICE_EXTENSIONS is not supported",
713 qCDebug(QRHI_LOG_INFO,
"Enabling device extensions:");
714 for (
const char *ext : requestedDevExts)
715 qCDebug(QRHI_LOG_INFO,
" %s", ext);
718 VkDeviceCreateInfo devInfo = {};
719 devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
720 devInfo.queueCreateInfoCount = 1;
721 devInfo.pQueueCreateInfos = &queueInfo;
722 devInfo.enabledLayerCount = uint32_t(devLayers.size());
723 devInfo.ppEnabledLayerNames = devLayers.constData();
724 devInfo.enabledExtensionCount = uint32_t(requestedDevExts.size());
725 devInfo.ppEnabledExtensionNames = requestedDevExts.constData();
741 physDevFeaturesChainable.features.robustBufferAccess = VK_FALSE;
744 physDevFeatures13.robustImageAccess = VK_FALSE;
755 devInfo.pNext = &physDevFeaturesChainable;
763 VkResult err =
f->vkCreateDevice(
physDev, &devInfo,
nullptr, &
dev);
764 if (err != VK_SUCCESS) {
765 qWarning(
"Failed to create device: %d", err);
769 qCDebug(QRHI_LOG_INFO,
"Using imported device %p", dev);
774 caps.vertexAttribDivisor =
true;
775 caps.renderPass2KHR =
true;
776 caps.depthStencilResolveKHR =
true;
779 vkGetPhysicalDeviceSurfaceCapabilitiesKHR =
reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
>(
780 inst->getInstanceProcAddr(
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
781 vkGetPhysicalDeviceSurfaceFormatsKHR =
reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
>(
782 inst->getInstanceProcAddr(
"vkGetPhysicalDeviceSurfaceFormatsKHR"));
783 vkGetPhysicalDeviceSurfacePresentModesKHR =
reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
>(
784 inst->getInstanceProcAddr(
"vkGetPhysicalDeviceSurfacePresentModesKHR"));
786 df = inst->deviceFunctions(dev);
788 VkCommandPoolCreateInfo poolInfo = {};
789 poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
790 poolInfo.queueFamilyIndex = gfxQueueFamilyIdx;
792 VkResult err = df->vkCreateCommandPool(dev, &poolInfo,
nullptr, &cmdPool[
i]);
793 if (err != VK_SUCCESS) {
794 qWarning(
"Failed to create command pool: %d", err);
799 qCDebug(QRHI_LOG_INFO,
"Using queue family index %u and queue index %u",
800 gfxQueueFamilyIdx, gfxQueueIdx);
802 df->vkGetDeviceQueue(dev, gfxQueueFamilyIdx, gfxQueueIdx, &gfxQueue);
804 if (queueFamilyProps.isEmpty())
805 queryQueueFamilyProps();
807 caps.compute = (queueFamilyProps[gfxQueueFamilyIdx].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0;
808 timestampValidBits = queueFamilyProps[gfxQueueFamilyIdx].timestampValidBits;
810 ubufAlign = physDevProperties.limits.minUniformBufferOffsetAlignment;
813 texbufAlign = qMax<VkDeviceSize>(4, physDevProperties.limits.optimalBufferCopyOffsetAlignment);
815 caps.wideLines = physDevFeatures.wideLines;
817 caps.texture3DSliceAs2D = caps.apiVersion >=
QVersionNumber(1, 1);
819 caps.tessellation = physDevFeatures.tessellationShader;
820 caps.geometryShader = physDevFeatures.geometryShader;
822 caps.nonFillPolygonMode = physDevFeatures.fillModeNonSolid;
826 caps.multiView = physDevFeatures11IfApi12OrNewer.multiview;
831 caps.multiView = multiviewFeaturesIfApi11.multiview;
838#ifdef VK_KHR_create_renderpass2
839 if (caps.renderPass2KHR) {
840 vkCreateRenderPass2KHR =
reinterpret_cast<PFN_vkCreateRenderPass2KHR
>(
f->vkGetDeviceProcAddr(dev,
"vkCreateRenderPass2KHR"));
841 if (!vkCreateRenderPass2KHR)
842 caps.renderPass2KHR =
false;
846 if (!importedAllocator) {
847 VmaVulkanFunctions
funcs = {};
851 VmaAllocatorCreateInfo allocatorInfo = {};
854 allocatorInfo.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
855 allocatorInfo.physicalDevice = physDev;
856 allocatorInfo.device = dev;
857 allocatorInfo.pVulkanFunctions = &
funcs;
858 allocatorInfo.instance = inst->vkInstance();
859 allocatorInfo.vulkanApiVersion = VK_MAKE_VERSION(caps.apiVersion.majorVersion(),
860 caps.apiVersion.minorVersion(),
861 caps.apiVersion.microVersion());
862 VmaAllocator vmaallocator;
863 VkResult err = vmaCreateAllocator(&allocatorInfo, &vmaallocator);
864 if (err != VK_SUCCESS) {
865 qWarning(
"Failed to create allocator: %d", err);
868 allocator = vmaallocator;
873 VkDescriptorPool
pool;
874 VkResult err = createDescriptorPool(&
pool);
875 if (err == VK_SUCCESS)
876 descriptorPools.append(
pool);
878 qWarning(
"Failed to create initial descriptor pool: %d", err);
880 VkQueryPoolCreateInfo timestampQueryPoolInfo = {};
881 timestampQueryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
882 timestampQueryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
884 err = df->vkCreateQueryPool(dev, ×tampQueryPoolInfo,
nullptr, ×tampQueryPool);
885 if (err != VK_SUCCESS) {
886 qWarning(
"Failed to create timestamp query pool: %d", err);
890 timestampQueryPoolMap.fill(
false);
892#ifdef VK_EXT_debug_utils
893 if (caps.debugUtils) {
894 vkSetDebugUtilsObjectNameEXT =
reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT
>(
f->vkGetDeviceProcAddr(dev,
"vkSetDebugUtilsObjectNameEXT"));
895 vkCmdBeginDebugUtilsLabelEXT =
reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT
>(
f->vkGetDeviceProcAddr(dev,
"vkCmdBeginDebugUtilsLabelEXT"));
896 vkCmdEndDebugUtilsLabelEXT =
reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT
>(
f->vkGetDeviceProcAddr(dev,
"vkCmdEndDebugUtilsLabelEXT"));
897 vkCmdInsertDebugUtilsLabelEXT =
reinterpret_cast<PFN_vkCmdInsertDebugUtilsLabelEXT
>(
f->vkGetDeviceProcAddr(dev,
"vkCmdInsertDebugUtilsLabelEXT"));
903 nativeHandlesStruct.physDev = physDev;
904 nativeHandlesStruct.dev = dev;
905 nativeHandlesStruct.gfxQueueFamilyIdx = gfxQueueFamilyIdx;
906 nativeHandlesStruct.gfxQueueIdx = gfxQueueIdx;
907 nativeHandlesStruct.gfxQueue = gfxQueue;
908 nativeHandlesStruct.vmemAllocator = allocator;
909 nativeHandlesStruct.inst = inst;
920 df->vkDeviceWaitIdle(
dev);
926 df->vkDestroyFence(
dev,
ofr.cmdFence,
nullptr);
927 ofr.cmdFence = VK_NULL_HANDLE;
936 df->vkDestroyDescriptorPool(
dev,
pool.pool,
nullptr);
956 ofr.cbWrapper[
i]->cb = VK_NULL_HANDLE;
960 df->vkDestroyDevice(
dev,
nullptr);
961 inst->resetDeviceFunctions(
dev);
962 dev = VK_NULL_HANDLE;
971 VkDescriptorPoolSize descPoolSizes[] = {
978 VkDescriptorPoolCreateInfo descPoolInfo = {};
979 descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
983 descPoolInfo.flags = 0;
985 descPoolInfo.poolSizeCount =
sizeof(descPoolSizes) /
sizeof(descPoolSizes[0]);
986 descPoolInfo.pPoolSizes = descPoolSizes;
987 return df->vkCreateDescriptorPool(
dev, &descPoolInfo,
nullptr,
pool);
992 auto tryAllocate = [
this, allocInfo,
result](
int poolIndex) {
994 VkResult
r =
df->vkAllocateDescriptorSets(
dev, allocInfo,
result);
1001 for (
int i = lastPoolIdx;
i >= 0; --
i) {
1007 VkResult err = tryAllocate(
i);
1008 if (err == VK_SUCCESS) {
1010 *resultPoolIndex =
i;
1016 VkDescriptorPool newPool;
1018 if (poolErr == VK_SUCCESS) {
1021 VkResult err = tryAllocate(lastPoolIdx);
1022 if (err != VK_SUCCESS) {
1023 qWarning(
"Failed to allocate descriptor set from new pool too, giving up: %d", err);
1026 descriptorPools[lastPoolIdx].allocedDescSets += allocInfo->descriptorSetCount;
1027 *resultPoolIndex = lastPoolIdx;
1030 qWarning(
"Failed to allocate new descriptor pool: %d", poolErr);
1040 return srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
1042 return srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
1044 return srgb ? VK_FORMAT_R8_SRGB : VK_FORMAT_R8_UNORM;
1046 return srgb ? VK_FORMAT_R8G8_SRGB : VK_FORMAT_R8G8_UNORM;
1048 return VK_FORMAT_R16_UNORM;
1050 return VK_FORMAT_R16G16_UNORM;
1052 return VK_FORMAT_R8_UNORM;
1055 return VK_FORMAT_R16G16B16A16_SFLOAT;
1057 return VK_FORMAT_R32G32B32A32_SFLOAT;
1059 return VK_FORMAT_R16_SFLOAT;
1061 return VK_FORMAT_R32_SFLOAT;
1065 return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
1068 return VK_FORMAT_D16_UNORM;
1070 return VK_FORMAT_X8_D24_UNORM_PACK32;
1072 return VK_FORMAT_D24_UNORM_S8_UINT;
1074 return VK_FORMAT_D32_SFLOAT;
1077 return srgb ? VK_FORMAT_BC1_RGB_SRGB_BLOCK : VK_FORMAT_BC1_RGB_UNORM_BLOCK;
1079 return srgb ? VK_FORMAT_BC2_SRGB_BLOCK : VK_FORMAT_BC2_UNORM_BLOCK;
1081 return srgb ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
1083 return VK_FORMAT_BC4_UNORM_BLOCK;
1085 return VK_FORMAT_BC5_UNORM_BLOCK;
1087 return VK_FORMAT_BC6H_UFLOAT_BLOCK;
1089 return srgb ? VK_FORMAT_BC7_SRGB_BLOCK : VK_FORMAT_BC7_UNORM_BLOCK;
1092 return srgb ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
1094 return srgb ? VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
1096 return srgb ? VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
1099 return srgb ? VK_FORMAT_ASTC_4x4_SRGB_BLOCK : VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
1101 return srgb ? VK_FORMAT_ASTC_5x4_SRGB_BLOCK : VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
1103 return srgb ? VK_FORMAT_ASTC_5x5_SRGB_BLOCK : VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
1105 return srgb ? VK_FORMAT_ASTC_6x5_SRGB_BLOCK : VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
1107 return srgb ? VK_FORMAT_ASTC_6x6_SRGB_BLOCK : VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
1109 return srgb ? VK_FORMAT_ASTC_8x5_SRGB_BLOCK : VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
1111 return srgb ? VK_FORMAT_ASTC_8x6_SRGB_BLOCK : VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
1113 return srgb ? VK_FORMAT_ASTC_8x8_SRGB_BLOCK : VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
1115 return srgb ? VK_FORMAT_ASTC_10x5_SRGB_BLOCK : VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
1117 return srgb ? VK_FORMAT_ASTC_10x6_SRGB_BLOCK : VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
1119 return srgb ? VK_FORMAT_ASTC_10x8_SRGB_BLOCK : VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
1121 return srgb ? VK_FORMAT_ASTC_10x10_SRGB_BLOCK : VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
1123 return srgb ? VK_FORMAT_ASTC_12x10_SRGB_BLOCK : VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
1125 return srgb ? VK_FORMAT_ASTC_12x12_SRGB_BLOCK : VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
1128 Q_UNREACHABLE_RETURN(VK_FORMAT_R8G8B8A8_UNORM);
1135 case VK_FORMAT_R8G8B8A8_UNORM:
1137 case VK_FORMAT_R8G8B8A8_SRGB:
1141 case VK_FORMAT_B8G8R8A8_UNORM:
1143 case VK_FORMAT_B8G8R8A8_SRGB:
1147 case VK_FORMAT_R16G16B16A16_SFLOAT:
1149 case VK_FORMAT_R32G32B32A32_SFLOAT:
1151 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
1186 VkPhysicalDeviceMemoryProperties physDevMemProps;
1187 f->vkGetPhysicalDeviceMemoryProperties(
physDev, &physDevMemProps);
1189 VkMemoryRequirements memReq;
1190 df->vkGetImageMemoryRequirements(
dev,
img, &memReq);
1191 uint32_t memTypeIndex = uint32_t(-1);
1193 if (memReq.memoryTypeBits) {
1195 const VkMemoryType *memType = physDevMemProps.memoryTypes;
1196 bool foundDevLocal =
false;
1197 for (uint32_t
i = startIndex;
i < physDevMemProps.memoryTypeCount; ++
i) {
1198 if (memReq.memoryTypeBits & (1 <<
i)) {
1199 if (memType[
i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
1200 if (!foundDevLocal) {
1201 foundDevLocal =
true;
1204 if (memType[
i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
1213 return memTypeIndex;
1217 const QSize &pixelSize,
1218 VkImageUsageFlags
usage,
1219 VkImageAspectFlags aspectMask,
1220 VkSampleCountFlagBits
samples,
1221 VkDeviceMemory *mem,
1226 VkMemoryRequirements memReq;
1230 VkImageCreateInfo imgInfo = {};
1231 imgInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1232 imgInfo.imageType = VK_IMAGE_TYPE_2D;
1234 imgInfo.extent.width = uint32_t(pixelSize.
width());
1235 imgInfo.extent.height = uint32_t(pixelSize.
height());
1236 imgInfo.extent.depth = 1;
1237 imgInfo.mipLevels = imgInfo.arrayLayers = 1;
1239 imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
1240 imgInfo.usage =
usage | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
1241 imgInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1243 err =
df->vkCreateImage(
dev, &imgInfo,
nullptr,
images +
i);
1244 if (err != VK_SUCCESS) {
1245 qWarning(
"Failed to create image: %d", err);
1252 df->vkGetImageMemoryRequirements(
dev,
images[
i], &memReq);
1255 VkMemoryAllocateInfo memInfo = {};
1256 memInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1257 memInfo.allocationSize =
aligned(memReq.size, memReq.alignment) * VkDeviceSize(
count);
1259 uint32_t startIndex = 0;
1262 if (memInfo.memoryTypeIndex == uint32_t(-1)) {
1263 qWarning(
"No suitable memory type found");
1266 startIndex = memInfo.memoryTypeIndex + 1;
1267 err =
df->vkAllocateMemory(
dev, &memInfo,
nullptr, mem);
1268 if (err != VK_SUCCESS && err != VK_ERROR_OUT_OF_DEVICE_MEMORY) {
1269 qWarning(
"Failed to allocate image memory: %d", err);
1272 }
while (err != VK_SUCCESS);
1274 VkDeviceSize ofs = 0;
1276 err =
df->vkBindImageMemory(
dev,
images[
i], *mem, ofs);
1277 if (err != VK_SUCCESS) {
1278 qWarning(
"Failed to bind image memory: %d", err);
1281 ofs +=
aligned(memReq.size, memReq.alignment);
1283 VkImageViewCreateInfo imgViewInfo = {};
1284 imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1285 imgViewInfo.image =
images[
i];
1286 imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
1287 imgViewInfo.format =
format;
1288 imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
1289 imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
1290 imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
1291 imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
1292 imgViewInfo.subresourceRange.aspectMask = aspectMask;
1293 imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
1295 err =
df->vkCreateImageView(
dev, &imgViewInfo,
nullptr, views +
i);
1296 if (err != VK_SUCCESS) {
1297 qWarning(
"Failed to create image view: %d", err);
1310 const VkFormat dsFormatCandidates[] = {
1311 VK_FORMAT_D24_UNORM_S8_UINT,
1312 VK_FORMAT_D32_SFLOAT_S8_UINT,
1313 VK_FORMAT_D16_UNORM_S8_UINT
1315 const int dsFormatCandidateCount =
sizeof(dsFormatCandidates) /
sizeof(VkFormat);
1316 int dsFormatIdx = 0;
1317 while (dsFormatIdx < dsFormatCandidateCount) {
1319 VkFormatProperties fmtProp;
1321 if (fmtProp.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
1325 if (dsFormatIdx == dsFormatCandidateCount)
1326 qWarning(
"Failed to find an optimal depth-stencil format");
1332 VkSubpassDescription *subpassDesc,
1335 memset(subpassDesc, 0,
sizeof(VkSubpassDescription));
1336 subpassDesc->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1337 subpassDesc->colorAttachmentCount = uint32_t(rpD->colorRefs.size());
1338 subpassDesc->pColorAttachments = !rpD->colorRefs.isEmpty() ? rpD->colorRefs.constData() :
nullptr;
1339 subpassDesc->pDepthStencilAttachment = rpD->hasDepthStencil ? &rpD->dsRef :
nullptr;
1340 subpassDesc->pResolveAttachments = !rpD->resolveRefs.isEmpty() ? rpD->resolveRefs.constData() :
nullptr;
1342 memset(rpInfo, 0,
sizeof(VkRenderPassCreateInfo));
1343 rpInfo->sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1344 rpInfo->attachmentCount = uint32_t(rpD->attDescs.size());
1345 rpInfo->pAttachments = rpD->attDescs.constData();
1346 rpInfo->subpassCount = 1;
1347 rpInfo->pSubpasses = subpassDesc;
1348 rpInfo->dependencyCount = uint32_t(rpD->subpassDeps.size());
1349 rpInfo->pDependencies = !rpD->subpassDeps.isEmpty() ? rpD->subpassDeps.constData() :
nullptr;
1356 VkAttachmentDescription attDesc = {};
1359 attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1360 attDesc.storeOp =
samples > VK_SAMPLE_COUNT_1_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
1361 attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1362 attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1363 attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1364 attDesc.finalLayout =
samples > VK_SAMPLE_COUNT_1_BIT ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
1365 rpD->attDescs.append(attDesc);
1367 rpD->colorRefs.append({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
1369 rpD->hasDepthStencil = hasDepthStencil;
1370 rpD->hasDepthStencilResolve =
false;
1371 rpD->multiViewCount = 0;
1373 if (hasDepthStencil) {
1376 memset(&attDesc, 0,
sizeof(attDesc));
1379 attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1380 attDesc.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1381 attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1382 attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1383 attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1384 attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1385 rpD->attDescs.append(attDesc);
1387 rpD->dsRef = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
1390 if (
samples > VK_SAMPLE_COUNT_1_BIT) {
1391 memset(&attDesc, 0,
sizeof(attDesc));
1393 attDesc.samples = VK_SAMPLE_COUNT_1_BIT;
1394 attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1395 attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1396 attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1397 attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1398 attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1399 attDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
1400 rpD->attDescs.append(attDesc);
1402 rpD->resolveRefs.append({ 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
1406 VkSubpassDependency subpassDep = {};
1407 subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL;
1408 subpassDep.dstSubpass = 0;
1409 subpassDep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1410 subpassDep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1411 subpassDep.srcAccessMask = 0;
1412 subpassDep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1413 rpD->subpassDeps.append(subpassDep);
1414 if (hasDepthStencil) {
1415 memset(&subpassDep, 0,
sizeof(subpassDep));
1416 subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL;
1417 subpassDep.dstSubpass = 0;
1418 subpassDep.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
1419 | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
1420 subpassDep.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
1421 | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
1422 subpassDep.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1423 subpassDep.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1424 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1425 rpD->subpassDeps.append(subpassDep);
1428 VkRenderPassCreateInfo rpInfo;
1429 VkSubpassDescription subpassDesc;
1432 VkResult err =
df->vkCreateRenderPass(
dev, &rpInfo,
nullptr, &rpD->rp);
1433 if (err != VK_SUCCESS) {
1434 qWarning(
"Failed to create renderpass: %d", err);
1443 bool prepare(VkRenderPassCreateInfo *rpInfo,
int multiViewCount,
bool multiViewCap)
1445 if (multiViewCount < 2)
1447 if (!multiViewCap) {
1448 qWarning(
"Cannot create multiview render pass without support for the Vulkan 1.1 multiview feature");
1451#ifdef VK_VERSION_1_1
1452 uint32_t allViewsMask = 0;
1453 for (uint32_t
i = 0;
i < uint32_t(multiViewCount); ++
i)
1454 allViewsMask |= (1 <<
i);
1455 multiViewMask = allViewsMask;
1456 multiViewCorrelationMask = allViewsMask;
1457 multiViewInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
1458 multiViewInfo.subpassCount = 1;
1459 multiViewInfo.pViewMasks = &multiViewMask;
1460 multiViewInfo.correlationMaskCount = 1;
1461 multiViewInfo.pCorrelationMasks = &multiViewCorrelationMask;
1462 rpInfo->pNext = &multiViewInfo;
1467#ifdef VK_VERSION_1_1
1468 VkRenderPassMultiviewCreateInfo multiViewInfo = {};
1469 uint32_t multiViewMask = 0;
1470 uint32_t multiViewCorrelationMask = 0;
1474#ifdef VK_KHR_create_renderpass2
1478struct RenderPass2SetupHelper
1480 bool prepare(VkRenderPassCreateInfo2 *rpInfo2,
const VkRenderPassCreateInfo *rpInfo,
const QVkRenderPassDescriptor *rpD,
int multiViewCount) {
1484 if (multiViewCount >= 2) {
1485 for (uint32_t
i = 0;
i < uint32_t(multiViewCount); ++
i)
1486 viewMask |= (1 <<
i);
1489 attDescs2.resize(rpInfo->attachmentCount);
1491 VkAttachmentDescription2KHR &att2(attDescs2[
i]);
1492 const VkAttachmentDescription &att(rpInfo->pAttachments[
i]);
1494 att2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
1495 att2.flags = att.flags;
1496 att2.format = att.format;
1497 att2.samples = att.samples;
1498 att2.loadOp = att.loadOp;
1499 att2.storeOp = att.storeOp;
1500 att2.stencilLoadOp = att.stencilLoadOp;
1501 att2.stencilStoreOp = att.stencilStoreOp;
1502 att2.initialLayout = att.initialLayout;
1503 att2.finalLayout = att.finalLayout;
1508 subpass2.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
1509 const VkSubpassDescription &subpassDesc(rpInfo->pSubpasses[0]);
1510 subpass2.flags = subpassDesc.flags;
1511 subpass2.pipelineBindPoint = subpassDesc.pipelineBindPoint;
1512 if (multiViewCount >= 2)
1513 subpass2.viewMask = viewMask;
1516 qsizetype startIndex = attRefs2.count();
1517 for (uint32_t
j = 0;
j < subpassDesc.colorAttachmentCount; ++
j) {
1518 attRefs2.append({});
1519 VkAttachmentReference2KHR &attref2(attRefs2.last());
1520 const VkAttachmentReference &attref(subpassDesc.pColorAttachments[
j]);
1521 attref2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
1522 attref2.attachment = attref.attachment;
1523 attref2.layout = attref.layout;
1524 attref2.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1526 subpass2.colorAttachmentCount = subpassDesc.colorAttachmentCount;
1527 subpass2.pColorAttachments = attRefs2.constData() + startIndex;
1530 if (subpassDesc.pResolveAttachments) {
1531 startIndex = attRefs2.count();
1532 for (uint32_t
j = 0;
j < subpassDesc.colorAttachmentCount; ++
j) {
1533 attRefs2.append({});
1534 VkAttachmentReference2KHR &attref2(attRefs2.last());
1535 const VkAttachmentReference &attref(subpassDesc.pResolveAttachments[
j]);
1536 attref2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
1537 attref2.attachment = attref.attachment;
1538 attref2.layout = attref.layout;
1539 attref2.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1541 subpass2.pResolveAttachments = attRefs2.constData() + startIndex;
1545 if (subpassDesc.pDepthStencilAttachment) {
1546 startIndex = attRefs2.count();
1547 attRefs2.append({});
1548 VkAttachmentReference2KHR &attref2(attRefs2.last());
1549 const VkAttachmentReference &attref(*subpassDesc.pDepthStencilAttachment);
1550 attref2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
1551 attref2.attachment = attref.attachment;
1552 attref2.layout = attref.layout;
1553 attref2.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1554 subpass2.pDepthStencilAttachment = attRefs2.constData() + startIndex;
1558#ifdef VK_KHR_depth_stencil_resolve
1560 if (rpD->hasDepthStencilResolve) {
1561 startIndex = attRefs2.count();
1562 attRefs2.append({});
1563 VkAttachmentReference2KHR &attref2(attRefs2.last());
1564 attref2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
1565 attref2.attachment = rpD->dsResolveRef.attachment;
1566 attref2.layout = rpD->dsResolveRef.layout;
1567 attref2.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1568 dsResolveDesc.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR;
1569 dsResolveDesc.depthResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1570 dsResolveDesc.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1571 dsResolveDesc.pDepthStencilResolveAttachment = attRefs2.constData() + startIndex;
1572 subpass2.pNext = &dsResolveDesc;
1576 rpInfo2->sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
1577 rpInfo2->pNext =
nullptr;
1578 rpInfo2->flags = rpInfo->flags;
1579 rpInfo2->attachmentCount = rpInfo->attachmentCount;
1580 rpInfo2->pAttachments = attDescs2.constData();
1581 rpInfo2->subpassCount = 1;
1582 rpInfo2->pSubpasses = &subpass2;
1583 if (multiViewCount >= 2) {
1584 rpInfo2->correlatedViewMaskCount = 1;
1585 rpInfo2->pCorrelatedViewMasks = &viewMask;
1590 QVarLengthArray<VkAttachmentDescription2KHR, 8> attDescs2;
1591 QVarLengthArray<VkAttachmentReference2KHR, 8> attRefs2;
1592 VkSubpassDescription2KHR subpass2;
1593#ifdef VK_KHR_depth_stencil_resolve
1594 VkSubpassDescriptionDepthStencilResolveKHR dsResolveDesc;
1612 int multiViewCount = 0;
1613 for (
auto it = colorAttachmentsBegin;
it != colorAttachmentsEnd; ++
it) {
1617 const VkFormat vkformat = texD ? texD->viewFormat : rbD->vkformat;
1618 const VkSampleCountFlagBits
samples = texD ? texD->samples : rbD->samples;
1620 VkAttachmentDescription attDesc = {};
1621 attDesc.format = vkformat;
1623 attDesc.loadOp = preserveColor ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
1624 attDesc.storeOp = (
it->resolveTexture() && !preserveColor) ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
1625 attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1626 attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1628 attDesc.initialLayout = preserveColor ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
1629 attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1630 rpD->attDescs.append(attDesc);
1632 const VkAttachmentReference
ref = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
1633 rpD->colorRefs.append(
ref);
1635 if (
it->multiViewCount() >= 2) {
1636 if (multiViewCount > 0 && multiViewCount !=
it->multiViewCount())
1637 qWarning(
"Inconsistent multiViewCount in color attachment set");
1639 multiViewCount =
it->multiViewCount();
1640 }
else if (multiViewCount > 0) {
1641 qWarning(
"Mixing non-multiview color attachments within a multiview render pass");
1644 Q_ASSERT(multiViewCount == 0 || multiViewCount >= 2);
1645 rpD->multiViewCount = uint32_t(multiViewCount);
1647 rpD->hasDepthStencil = depthStencilBuffer || depthTexture;
1648 if (rpD->hasDepthStencil) {
1649 const VkFormat dsFormat = depthTexture ?
QRHI_RES(
QVkTexture, depthTexture)->viewFormat
1653 const VkAttachmentLoadOp loadOp = preserveDs ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
1654 const VkAttachmentStoreOp storeOp = storeDs ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
1655 VkAttachmentDescription attDesc = {};
1656 attDesc.format = dsFormat;
1658 attDesc.loadOp = loadOp;
1659 attDesc.storeOp = storeOp;
1660 attDesc.stencilLoadOp = loadOp;
1661 attDesc.stencilStoreOp = storeOp;
1662 attDesc.initialLayout = preserveDs ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
1663 attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1664 rpD->attDescs.append(attDesc);
1665 if (depthTexture && depthTexture->
arraySize() >= 2 && colorAttachmentsBegin == colorAttachmentsEnd) {
1666 multiViewCount = depthTexture->
arraySize();
1667 rpD->multiViewCount = multiViewCount;
1670 rpD->dsRef = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
1672 for (
auto it = colorAttachmentsBegin;
it != colorAttachmentsEnd; ++
it) {
1673 if (
it->resolveTexture()) {
1675 const VkFormat dstFormat = rtexD->vkformat;
1676 if (rtexD->samples > VK_SAMPLE_COUNT_1_BIT)
1677 qWarning(
"Resolving into a multisample texture is not supported");
1681 const VkFormat srcFormat = texD ? texD->vkformat : rbD->vkformat;
1682 if (srcFormat != dstFormat) {
1686 qWarning(
"Multisample resolve between different formats (%d and %d) is not supported.",
1687 int(srcFormat),
int(dstFormat));
1690 VkAttachmentDescription attDesc = {};
1691 attDesc.format = rtexD->viewFormat;
1692 attDesc.samples = VK_SAMPLE_COUNT_1_BIT;
1693 attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1694 attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1695 attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1696 attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1697 attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1698 attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1699 rpD->attDescs.append(attDesc);
1701 const VkAttachmentReference
ref = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
1702 rpD->resolveRefs.append(
ref);
1704 const VkAttachmentReference
ref = { VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
1705 rpD->resolveRefs.append(
ref);
1708 Q_ASSERT(rpD->colorRefs.size() == rpD->resolveRefs.size());
1710 rpD->hasDepthStencilResolve = rpD->hasDepthStencil && depthResolveTexture;
1711 if (rpD->hasDepthStencilResolve) {
1713 if (rtexD->samples > VK_SAMPLE_COUNT_1_BIT)
1714 qWarning(
"Resolving into a multisample depth texture is not supported");
1717 if (texD->vkformat != rtexD->vkformat) {
1718 qWarning(
"Multisample resolve between different depth-stencil formats (%d and %d) is not supported.",
1719 int(texD->vkformat),
int(rtexD->vkformat));
1722 VkAttachmentDescription attDesc = {};
1723 attDesc.format = rtexD->viewFormat;
1724 attDesc.samples = VK_SAMPLE_COUNT_1_BIT;
1725 attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1726 attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1727 attDesc.stencilLoadOp = attDesc.loadOp;
1728 attDesc.stencilStoreOp = attDesc.storeOp;
1729 attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1730 attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1731 rpD->attDescs.append(attDesc);
1733 rpD->dsResolveRef = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
1740 VkRenderPassCreateInfo rpInfo;
1741 VkSubpassDescription subpassDesc;
1745 if (!multiViewHelper.prepare(&rpInfo, multiViewCount,
caps.multiView))
1748#ifdef VK_KHR_create_renderpass2
1749 if (rpD->hasDepthStencilResolve &&
caps.renderPass2KHR) {
1751 VkRenderPassCreateInfo2KHR rpInfo2;
1752 RenderPass2SetupHelper rp2Helper;
1753 if (!rp2Helper.prepare(&rpInfo2, &rpInfo, rpD, multiViewCount))
1756 VkResult err = vkCreateRenderPass2KHR(
dev, &rpInfo2,
nullptr, &rpD->rp);
1757 if (err != VK_SUCCESS) {
1758 qWarning(
"Failed to create renderpass (using VkRenderPassCreateInfo2KHR): %d", err);
1764 if (rpD->hasDepthStencilResolve) {
1765 qWarning(
"Resolving multisample depth-stencil buffers is not supported without "
1766 "VK_KHR_depth_stencil_resolve and VK_KHR_create_renderpass2");
1768 VkResult err =
df->vkCreateRenderPass(
dev, &rpInfo,
nullptr, &rpD->rp);
1769 if (err != VK_SUCCESS) {
1770 qWarning(
"Failed to create renderpass: %d", err);
1781 if (swapChainD->pixelSize.isEmpty()) {
1782 qWarning(
"Surface size is 0, cannot create swapchain");
1786 df->vkDeviceWaitIdle(
dev);
1789 vkCreateSwapchainKHR =
reinterpret_cast<PFN_vkCreateSwapchainKHR
>(
f->vkGetDeviceProcAddr(
dev,
"vkCreateSwapchainKHR"));
1790 vkDestroySwapchainKHR =
reinterpret_cast<PFN_vkDestroySwapchainKHR
>(
f->vkGetDeviceProcAddr(
dev,
"vkDestroySwapchainKHR"));
1792 vkAcquireNextImageKHR =
reinterpret_cast<PFN_vkAcquireNextImageKHR
>(
f->vkGetDeviceProcAddr(
dev,
"vkAcquireNextImageKHR"));
1793 vkQueuePresentKHR =
reinterpret_cast<PFN_vkQueuePresentKHR
>(
f->vkGetDeviceProcAddr(
dev,
"vkQueuePresentKHR"));
1795 qWarning(
"Swapchain functions not available");
1800 VkSurfaceCapabilitiesKHR surfaceCaps;
1804 reqBufferCount = qMax<quint32>(2, surfaceCaps.minImageCount);
1806 reqBufferCount =
qMax(qMin<quint32>(surfaceCaps.maxImageCount, 3), surfaceCaps.minImageCount);
1808 VkSurfaceTransformFlagBitsKHR preTransform =
1809 (surfaceCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
1810 ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
1811 : surfaceCaps.currentTransform;
1837 VkCompositeAlphaFlagBitsKHR compositeAlpha =
1838 (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
1839 ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
1840 : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
1843 if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
1844 compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
1845 else if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
1846 compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
1848 if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
1849 compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
1850 else if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
1851 compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
1854 VkImageUsageFlags
usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1855 swapChainD->supportsReadback = (surfaceCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1857 usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1859 const bool stereo = bool(swapChainD->m_window) && (swapChainD->m_window->format().stereo())
1860 && surfaceCaps.maxImageArrayLayers > 1;
1861 swapChainD->stereo = stereo;
1863 VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
1868 if (swapChainD->supportedPresentationModes.contains(VK_PRESENT_MODE_MAILBOX_KHR) && !stereo)
1869 presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
1870 else if (swapChainD->supportedPresentationModes.contains(VK_PRESENT_MODE_IMMEDIATE_KHR))
1871 presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
1879 const bool reuseExisting = swapChainD->sc && swapChainD->lastConnectedSurface == swapChainD->surface;
1881 qCDebug(QRHI_LOG_INFO,
"Creating %s swapchain of %u buffers, size %dx%d, presentation mode %d",
1882 reuseExisting ?
"recycled" :
"new",
1883 reqBufferCount, swapChainD->pixelSize.width(), swapChainD->pixelSize.height(), presentMode);
1885 VkSwapchainCreateInfoKHR swapChainInfo = {};
1886 swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
1887 swapChainInfo.surface = swapChainD->surface;
1888 swapChainInfo.minImageCount = reqBufferCount;
1889 swapChainInfo.imageFormat = swapChainD->colorFormat;
1890 swapChainInfo.imageColorSpace = swapChainD->colorSpace;
1891 swapChainInfo.imageExtent = VkExtent2D { uint32_t(swapChainD->pixelSize.width()), uint32_t(swapChainD->pixelSize.height()) };
1892 swapChainInfo.imageArrayLayers = stereo ? 2u : 1u;
1893 swapChainInfo.imageUsage =
usage;
1894 swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
1895 swapChainInfo.preTransform = preTransform;
1896 swapChainInfo.compositeAlpha = compositeAlpha;
1897 swapChainInfo.presentMode = presentMode;
1898 swapChainInfo.clipped =
true;
1899 swapChainInfo.oldSwapchain = reuseExisting ? swapChainD->sc : VK_NULL_HANDLE;
1901 VkSwapchainKHR newSwapChain;
1903 if (err != VK_SUCCESS) {
1904 qWarning(
"Failed to create swapchain: %d", err);
1911 swapChainD->sc = newSwapChain;
1912 swapChainD->lastConnectedSurface = swapChainD->surface;
1914 quint32 actualSwapChainBufferCount = 0;
1916 if (err != VK_SUCCESS || actualSwapChainBufferCount == 0) {
1917 qWarning(
"Failed to get swapchain images: %d", err);
1921 if (actualSwapChainBufferCount != reqBufferCount)
1922 qCDebug(QRHI_LOG_INFO,
"Actual swapchain buffer count is %u", actualSwapChainBufferCount);
1923 swapChainD->bufferCount = int(actualSwapChainBufferCount);
1925 QVarLengthArray<VkImage, QVkSwapChain::EXPECTED_MAX_BUFFER_COUNT> swapChainImages(actualSwapChainBufferCount);
1927 if (err != VK_SUCCESS) {
1928 qWarning(
"Failed to get swapchain images: %d", err);
1932 QVarLengthArray<VkImage, QVkSwapChain::EXPECTED_MAX_BUFFER_COUNT> msaaImages(swapChainD->bufferCount);
1933 QVarLengthArray<VkImageView, QVkSwapChain::EXPECTED_MAX_BUFFER_COUNT> msaaViews(swapChainD->bufferCount);
1934 if (swapChainD->samples > VK_SAMPLE_COUNT_1_BIT) {
1936 swapChainD->pixelSize,
1937 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1938 VK_IMAGE_ASPECT_COLOR_BIT,
1939 swapChainD->samples,
1940 &swapChainD->msaaImageMem,
1943 swapChainD->bufferCount))
1945 qWarning(
"Failed to create transient image for MSAA color buffer");
1950 VkFenceCreateInfo fenceInfo = {};
1951 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1952 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
1955 swapChainD->imageRes.resize(swapChainD->bufferCount * (stereo ? 2u : 1u));
1957 for (
int i = 0;
i < swapChainD->bufferCount; ++
i) {
1959 image.image = swapChainImages[
i];
1960 if (swapChainD->samples > VK_SAMPLE_COUNT_1_BIT) {
1961 image.msaaImage = msaaImages[
i];
1962 image.msaaImageView = msaaViews[
i];
1965 VkImageViewCreateInfo imgViewInfo = {};
1966 imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1967 imgViewInfo.image = swapChainImages[
i];
1968 imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
1969 imgViewInfo.format = swapChainD->colorFormat;
1970 imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
1971 imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
1972 imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
1973 imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
1974 imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1975 imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
1976 err =
df->vkCreateImageView(
dev, &imgViewInfo,
nullptr, &
image.imageView);
1977 if (err != VK_SUCCESS) {
1978 qWarning(
"Failed to create swapchain image view %d: %d",
i, err);
1985 for (
int i = 0;
i < swapChainD->bufferCount; ++
i) {
1987 image.image = swapChainImages[
i];
1988 if (swapChainD->samples > VK_SAMPLE_COUNT_1_BIT) {
1989 image.msaaImage = msaaImages[
i];
1990 image.msaaImageView = msaaViews[
i];
1993 VkImageViewCreateInfo imgViewInfo = {};
1994 imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1995 imgViewInfo.image = swapChainImages[
i];
1996 imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
1997 imgViewInfo.format = swapChainD->colorFormat;
1998 imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
1999 imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
2000 imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
2001 imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
2002 imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2003 imgViewInfo.subresourceRange.baseArrayLayer = 1;
2004 imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
2005 err =
df->vkCreateImageView(
dev, &imgViewInfo,
nullptr, &
image.imageView);
2006 if (err != VK_SUCCESS) {
2007 qWarning(
"Failed to create swapchain image view %d: %d",
i, err);
2015 swapChainD->currentImageIndex = 0;
2017 VkSemaphoreCreateInfo semInfo = {};
2018 semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
2023 frame.imageAcquired =
false;
2024 frame.imageSemWaitable =
false;
2026 df->vkCreateFence(
dev, &fenceInfo,
nullptr, &
frame.imageFence);
2027 frame.imageFenceWaitable =
true;
2029 df->vkCreateSemaphore(
dev, &semInfo,
nullptr, &
frame.imageSem);
2030 df->vkCreateSemaphore(
dev, &semInfo,
nullptr, &
frame.drawSem);
2032 err =
df->vkCreateFence(
dev, &fenceInfo,
nullptr, &
frame.cmdFence);
2033 if (err != VK_SUCCESS) {
2034 qWarning(
"Failed to create command buffer fence: %d", err);
2037 frame.cmdFenceWaitable =
true;
2040 swapChainD->currentFrameSlot = 0;
2049 if (swapChainD->sc == VK_NULL_HANDLE)
2053 df->vkDeviceWaitIdle(
dev);
2057 if (
frame.cmdFence) {
2058 if (
frame.cmdFenceWaitable)
2059 df->vkWaitForFences(
dev, 1, &
frame.cmdFence, VK_TRUE, UINT64_MAX);
2060 df->vkDestroyFence(
dev,
frame.cmdFence,
nullptr);
2061 frame.cmdFence = VK_NULL_HANDLE;
2062 frame.cmdFenceWaitable =
false;
2064 if (
frame.imageFence) {
2065 if (
frame.imageFenceWaitable)
2066 df->vkWaitForFences(
dev, 1, &
frame.imageFence, VK_TRUE, UINT64_MAX);
2067 df->vkDestroyFence(
dev,
frame.imageFence,
nullptr);
2068 frame.imageFence = VK_NULL_HANDLE;
2069 frame.imageFenceWaitable =
false;
2071 if (
frame.imageSem) {
2072 df->vkDestroySemaphore(
dev,
frame.imageSem,
nullptr);
2073 frame.imageSem = VK_NULL_HANDLE;
2075 if (
frame.drawSem) {
2076 df->vkDestroySemaphore(
dev,
frame.drawSem,
nullptr);
2077 frame.drawSem = VK_NULL_HANDLE;
2081 for (
int i = 0;
i < swapChainD->bufferCount * (swapChainD->stereo ? 2 : 1); ++
i) {
2084 df->vkDestroyFramebuffer(
dev,
image.fb,
nullptr);
2085 image.fb = VK_NULL_HANDLE;
2087 if (
image.imageView) {
2088 df->vkDestroyImageView(
dev,
image.imageView,
nullptr);
2089 image.imageView = VK_NULL_HANDLE;
2091 if (
image.msaaImageView) {
2092 df->vkDestroyImageView(
dev,
image.msaaImageView,
nullptr);
2093 image.msaaImageView = VK_NULL_HANDLE;
2095 if (
image.msaaImage) {
2096 df->vkDestroyImage(
dev,
image.msaaImage,
nullptr);
2097 image.msaaImage = VK_NULL_HANDLE;
2101 if (swapChainD->msaaImageMem) {
2102 df->vkFreeMemory(
dev, swapChainD->msaaImageMem,
nullptr);
2103 swapChainD->msaaImageMem = VK_NULL_HANDLE;
2107 swapChainD->sc = VK_NULL_HANDLE;
2114 VkCommandPoolResetFlags
flags = 0;
2120 flags |= VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT;
2130 mask |= 0xFFULL <<
i;
2135 const float elapsedMs = float(ts1 - ts0) * nsecsPerTick / 1000000.0f;
2136 const double elapsedSec = elapsedMs / 1000.0;
2147 const int frameResIndex = swapChainD->bufferCount > 1 ? swapChainD->currentFrameSlot : 0;
2150 inst->handle()->beginFrame(swapChainD->window);
2152 if (!
frame.imageAcquired) {
2155 if (
frame.imageFenceWaitable) {
2156 df->vkWaitForFences(
dev, 1, &
frame.imageFence, VK_TRUE, UINT64_MAX);
2157 df->vkResetFences(
dev, 1, &
frame.imageFence);
2158 frame.imageFenceWaitable =
false;
2162 uint32_t imageIndex = 0;
2164 frame.imageSem,
frame.imageFence, &imageIndex);
2165 if (err == VK_SUCCESS || err == VK_SUBOPTIMAL_KHR) {
2166 swapChainD->currentImageIndex = imageIndex;
2167 frame.imageSemWaitable =
true;
2168 frame.imageAcquired =
true;
2169 frame.imageFenceWaitable =
true;
2170 }
else if (err == VK_ERROR_OUT_OF_DATE_KHR) {
2173 if (err == VK_ERROR_DEVICE_LOST) {
2174 qWarning(
"Device loss detected in vkAcquireNextImageKHR()");
2178 qWarning(
"Failed to acquire next swapchain image: %d", err);
2208 swapChainD->cbWrapper.cb =
frame.cmdBuf;
2211 swapChainD->rtWrapper.d.fb =
image.fb;
2213 if (swapChainD->stereo) {
2215 swapChainD->imageRes[swapChainD->currentImageIndex + swapChainD->bufferCount]);
2216 swapChainD->rtWrapperRight.d.fb =
image.fb;
2222 if (
frame.timestampQueryIndex >= 0) {
2223 quint64 timestamp[2] = { 0, 0 };
2226 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
2228 frame.timestampQueryIndex = -1;
2229 if (err == VK_SUCCESS) {
2233 swapChainD->cbWrapper.lastGpuTime = elapsedSec;
2235 qWarning(
"Failed to query timestamp: %d", err);
2241 int timestampQueryIdx = -1;
2245 timestampQueryIdx =
i * 2;
2249 if (timestampQueryIdx >= 0) {
2252 df->vkCmdWriteTimestamp(
frame.cmdBuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2254 frame.timestampQueryIndex = timestampQueryIdx;
2272 int frameResIndex = swapChainD->bufferCount > 1 ? swapChainD->currentFrameSlot : 0;
2277 VkImageMemoryBarrier presTrans = {};
2278 presTrans.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2279 presTrans.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2280 presTrans.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
2281 presTrans.image =
image.image;
2282 presTrans.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2283 presTrans.subresourceRange.levelCount = presTrans.subresourceRange.layerCount = 1;
2287 presTrans.srcAccessMask = 0;
2288 presTrans.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
2289 df->vkCmdPipelineBarrier(
frame.cmdBuf,
2290 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2291 0, 0,
nullptr, 0,
nullptr,
2295 presTrans.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
2296 presTrans.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
2297 df->vkCmdPipelineBarrier(
frame.cmdBuf,
2298 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2299 0, 0,
nullptr, 0,
nullptr,
2306 if (
frame.timestampQueryIndex >= 0) {
2307 df->vkCmdWriteTimestamp(
frame.cmdBuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
2316 frame.imageSemWaitable ? &
frame.imageSem :
nullptr,
2317 needsPresent ? &
frame.drawSem :
nullptr);
2321 frame.imageSemWaitable =
false;
2322 frame.cmdFenceWaitable =
true;
2326 VkPresentInfoKHR presInfo = {};
2327 presInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
2328 presInfo.swapchainCount = 1;
2329 presInfo.pSwapchains = &swapChainD->sc;
2330 presInfo.pImageIndices = &swapChainD->currentImageIndex;
2331 presInfo.waitSemaphoreCount = 1;
2332 presInfo.pWaitSemaphores = &
frame.drawSem;
2336 inst->presentAboutToBeQueued(swapChainD->window);
2339 if (err != VK_SUCCESS) {
2340 if (err == VK_ERROR_OUT_OF_DATE_KHR) {
2342 }
else if (err != VK_SUBOPTIMAL_KHR) {
2343 if (err == VK_ERROR_DEVICE_LOST) {
2344 qWarning(
"Device loss detected in vkQueuePresentKHR()");
2348 qWarning(
"Failed to present: %d", err);
2355 inst->presentQueued(swapChainD->window);
2358 frame.imageAcquired =
false;
2363 swapChainD->frameCount += 1;
2394 VkCommandBufferAllocateInfo cmdBufInfo = {};
2395 cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
2397 cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
2398 cmdBufInfo.commandBufferCount = 1;
2400 VkResult err =
df->vkAllocateCommandBuffers(
dev, &cmdBufInfo,
cb);
2401 if (err != VK_SUCCESS) {
2402 if (err == VK_ERROR_DEVICE_LOST) {
2403 qWarning(
"Device loss detected in vkAllocateCommandBuffers()");
2407 qWarning(
"Failed to allocate frame command buffer: %d", err);
2412 VkCommandBufferBeginInfo cmdBufBeginInfo = {};
2413 cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2415 VkResult err =
df->vkBeginCommandBuffer(*
cb, &cmdBufBeginInfo);
2416 if (err != VK_SUCCESS) {
2417 if (err == VK_ERROR_DEVICE_LOST) {
2418 qWarning(
"Device loss detected in vkBeginCommandBuffer()");
2422 qWarning(
"Failed to begin frame command buffer: %d", err);
2430 VkSemaphore *waitSem, VkSemaphore *signalSem)
2432 VkResult err =
df->vkEndCommandBuffer(
cb);
2433 if (err != VK_SUCCESS) {
2434 if (err == VK_ERROR_DEVICE_LOST) {
2435 qWarning(
"Device loss detected in vkEndCommandBuffer()");
2439 qWarning(
"Failed to end frame command buffer: %d", err);
2443 VkSubmitInfo submitInfo = {};
2444 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2445 submitInfo.commandBufferCount = 1;
2446 submitInfo.pCommandBuffers = &
cb;
2448 submitInfo.waitSemaphoreCount = 1;
2449 submitInfo.pWaitSemaphores = waitSem;
2452 submitInfo.signalSemaphoreCount = 1;
2453 submitInfo.pSignalSemaphores = signalSem;
2455 VkPipelineStageFlags psf = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2456 submitInfo.pWaitDstStageMask = &psf;
2458 err =
df->vkQueueSubmit(
gfxQueue, 1, &submitInfo, cmdFence);
2459 if (err != VK_SUCCESS) {
2460 if (err == VK_ERROR_DEVICE_LOST) {
2461 qWarning(
"Device loss detected in vkQueueSubmit()");
2465 qWarning(
"Failed to submit to graphics queue: %d", err);
2475 const int frameResIndex = sc->bufferCount > 1 ? frameSlot : 0;
2477 if (
frame.cmdFenceWaitable) {
2478 df->vkWaitForFences(
dev, 1, &
frame.cmdFence, VK_TRUE, UINT64_MAX);
2480 frame.cmdFenceWaitable =
false;
2511 int timestampQueryIdx = -1;
2515 timestampQueryIdx =
i * 2;
2519 if (timestampQueryIdx >= 0) {
2522 df->vkCmdWriteTimestamp(cbWrapper->
cb, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2524 ofr.timestampQueryIndex = timestampQueryIdx;
2542 if (
ofr.timestampQueryIndex >= 0) {
2543 df->vkCmdWriteTimestamp(cbWrapper->
cb, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
2547 if (!
ofr.cmdFence) {
2548 VkFenceCreateInfo fenceInfo = {};
2549 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
2550 VkResult err =
df->vkCreateFence(
dev, &fenceInfo,
nullptr, &
ofr.cmdFence);
2551 if (err != VK_SUCCESS) {
2552 qWarning(
"Failed to create command buffer fence: %d", err);
2562 df->vkWaitForFences(
dev, 1, &
ofr.cmdFence, VK_TRUE, UINT64_MAX);
2563 df->vkResetFences(
dev, 1, &
ofr.cmdFence);
2570 if (
ofr.timestampQueryIndex >= 0) {
2571 quint64 timestamp[2] = { 0, 0 };
2574 VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
2576 ofr.timestampQueryIndex = -1;
2577 if (err == VK_SUCCESS) {
2583 qWarning(
"Failed to query timestamp: %d", err);
2609 swapChainD->cbWrapper.resetCommands();
2610 cb = swapChainD->cbWrapper.cb;
2628 swapChainD->cbWrapper.cb =
frame.cmdBuf;
2642 u.
access = int(bufUsage.access);
2643 u.
stage = int(bufUsage.stage);
2650 u.
layout = texUsage.layout;
2651 u.
access = int(texUsage.access);
2652 u.
stage = int(texUsage.stage);
2658 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QVkTexture, QVkRenderBuffer>(rtD->description(), rtD->d.currentResIdList))
2664 for (
auto it = rtD->m_desc.cbeginColorAttachments(), itEnd = rtD->m_desc.cendColorAttachments();
it != itEnd; ++
it) {
2686 if (rtD->m_desc.depthStencilBuffer()) {
2697 if (rtD->m_desc.depthTexture()) {
2704 if (rtD->m_desc.depthResolveTexture()) {
2723 VkCommandBuffer secondaryCb;
2729 VkCommandBufferAllocateInfo cmdBufInfo = {};
2730 cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
2732 cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
2733 cmdBufInfo.commandBufferCount = 1;
2735 VkResult err =
df->vkAllocateCommandBuffers(
dev, &cmdBufInfo, &secondaryCb);
2736 if (err != VK_SUCCESS) {
2737 qWarning(
"Failed to create secondary command buffer: %d", err);
2738 return VK_NULL_HANDLE;
2742 VkCommandBufferBeginInfo cmdBufBeginInfo = {};
2743 cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2744 cmdBufBeginInfo.flags = rtD ? VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT : 0;
2745 VkCommandBufferInheritanceInfo cmdBufInheritInfo = {};
2746 cmdBufInheritInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
2747 cmdBufInheritInfo.subpass = 0;
2749 cmdBufInheritInfo.renderPass = rtD->rp->rp;
2750 cmdBufInheritInfo.framebuffer = rtD->fb;
2752 cmdBufBeginInfo.pInheritanceInfo = &cmdBufInheritInfo;
2754 VkResult err =
df->vkBeginCommandBuffer(secondaryCb, &cmdBufBeginInfo);
2755 if (err != VK_SUCCESS) {
2756 qWarning(
"Failed to begin secondary command buffer: %d", err);
2757 return VK_NULL_HANDLE;
2765 VkResult err =
df->vkEndCommandBuffer(
cb);
2766 if (err != VK_SUCCESS)
2767 qWarning(
"Failed to end secondary command buffer: %d", err);
2771 cmd.
args.executeSecondary.cb =
cb;
2782 const QColor &colorClearValue,
2785 QRhiCommandBuffer::BeginPassFlags
flags)
2790 if (resourceUpdates)
2827 VkRenderPassBeginInfo rpBeginInfo = {};
2828 rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2829 rpBeginInfo.renderPass = rtD->rp->rp;
2830 rpBeginInfo.framebuffer = rtD->fb;
2831 rpBeginInfo.renderArea.extent.width = uint32_t(rtD->pixelSize.width());
2832 rpBeginInfo.renderArea.extent.height = uint32_t(rtD->pixelSize.height());
2834 QVarLengthArray<VkClearValue, 4> cvs;
2835 for (
int i = 0;
i < rtD->colorAttCount; ++
i) {
2837 cv.color = { { float(colorClearValue.redF()), float(colorClearValue.greenF()), float(colorClearValue.blueF()),
2838 float(colorClearValue.alphaF()) } };
2841 for (
int i = 0;
i < rtD->dsAttCount; ++
i) {
2843 cv.depthStencil = { depthStencilClearValue.depthClearValue(), depthStencilClearValue.stencilClearValue() };
2846 for (
int i = 0;
i < rtD->resolveAttCount; ++
i) {
2848 cv.color = { { float(colorClearValue.redF()), float(colorClearValue.greenF()), float(colorClearValue.blueF()),
2849 float(colorClearValue.alphaF()) } };
2852 for (
int i = 0;
i < rtD->dsResolveAttCount; ++
i) {
2854 cv.depthStencil = { depthStencilClearValue.depthClearValue(), depthStencilClearValue.stencilClearValue() };
2857 rpBeginInfo.clearValueCount = uint32_t(cvs.size());
2861 cmd.
args.beginRenderPass.desc = rpBeginInfo;
2862 cmd.
args.beginRenderPass.clearValueIndex = cbD->
pools.clearValue.size();
2864 cbD->
pools.clearValue.append(cvs.constData(), cvs.size());
2889 if (resourceUpdates)
2895 QRhiCommandBuffer::BeginPassFlags
flags)
2900 if (resourceUpdates)
2929 if (resourceUpdates)
2946 cmd.
args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
2947 cmd.
args.bindPipeline.pipeline = psD->pipeline;
2961 int loadTypeVal,
int storeTypeVal,
int loadStoreTypeVal)
2963 VkAccessFlags
access = 0;
2964 if (bindingType == loadTypeVal) {
2965 access = VK_ACCESS_SHADER_READ_BIT;
2967 access = VK_ACCESS_SHADER_WRITE_BIT;
2968 if (bindingType == loadStoreTypeVal)
2969 access |= VK_ACCESS_SHADER_READ_BIT;
2971 auto it = writtenResources->find(resource);
2972 if (
it != writtenResources->end())
2974 else if (bindingType == storeTypeVal || bindingType == loadStoreTypeVal)
2975 writtenResources->insert(resource, {
access,
true });
2985 QVarLengthArray<VkImageMemoryBarrier, 8> imageBarriers;
2986 QVarLengthArray<VkBufferMemoryBarrier, 8> bufferBarriers;
2992 accessAndIsNewFlag = { 0,
false };
2995 const int bindingCount = srbD->m_bindings.size();
2996 for (
int i = 0;
i < bindingCount; ++
i) {
3025 const int accessInThisDispatch =
it->first;
3026 const bool isNewInThisDispatch =
it->second;
3027 if (accessInThisDispatch && !isNewInThisDispatch) {
3030 VkImageMemoryBarrier barrier = {};
3031 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
3032 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3034 barrier.subresourceRange.baseMipLevel = 0;
3035 barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
3036 barrier.subresourceRange.baseArrayLayer = 0;
3037 barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
3038 barrier.oldLayout = texD->usageState.layout;
3039 barrier.newLayout = texD->usageState.layout;
3040 barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
3041 barrier.dstAccessMask = accessInThisDispatch;
3042 barrier.image = texD->image;
3043 imageBarriers.append(barrier);
3046 VkBufferMemoryBarrier barrier = {};
3047 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
3048 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
3049 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
3050 barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
3051 barrier.dstAccessMask = accessInThisDispatch;
3053 barrier.size = VK_WHOLE_SIZE;
3054 bufferBarriers.append(barrier);
3060 if (accessInThisDispatch == VK_ACCESS_SHADER_READ_BIT)
3069 if (!imageBarriers.isEmpty()) {
3070 df->vkCmdPipelineBarrier(secondaryCb, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3073 imageBarriers.size(), imageBarriers.constData());
3075 if (!bufferBarriers.isEmpty()) {
3076 df->vkCmdPipelineBarrier(secondaryCb, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3078 bufferBarriers.size(), bufferBarriers.constData(),
3081 df->vkCmdDispatch(secondaryCb, uint32_t(
x), uint32_t(
y), uint32_t(
z));
3083 if (!imageBarriers.isEmpty()) {
3086 cmd.
args.imageBarrier.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
3087 cmd.
args.imageBarrier.dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
3088 cmd.
args.imageBarrier.count = imageBarriers.size();
3089 cmd.
args.imageBarrier.index = cbD->
pools.imageBarrier.size();
3090 cbD->
pools.imageBarrier.append(imageBarriers.constData(), imageBarriers.size());
3092 if (!bufferBarriers.isEmpty()) {
3095 cmd.
args.bufferBarrier.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
3096 cmd.
args.bufferBarrier.dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
3097 cmd.
args.bufferBarrier.count = bufferBarriers.size();
3098 cmd.
args.bufferBarrier.index = cbD->
pools.bufferBarrier.size();
3099 cbD->
pools.bufferBarrier.append(bufferBarriers.constData(), bufferBarriers.size());
3103 cmd.
args.dispatch.x =
x;
3104 cmd.
args.dispatch.y =
y;
3105 cmd.
args.dispatch.z =
z;
3111 VkShaderModuleCreateInfo shaderInfo = {};
3112 shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
3113 shaderInfo.codeSize = size_t(spirv.size());
3114 shaderInfo.pCode =
reinterpret_cast<const quint32 *
>(spirv.constData());
3115 VkShaderModule shaderModule;
3116 VkResult err =
df->vkCreateShaderModule(
dev, &shaderInfo,
nullptr, &shaderModule);
3117 if (err != VK_SUCCESS) {
3118 qWarning(
"Failed to create shader module: %d", err);
3119 return VK_NULL_HANDLE;
3121 return shaderModule;
3129 VkPipelineCacheCreateInfo pipelineCacheInfo = {};
3130 pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
3131 pipelineCacheInfo.initialDataSize = initialDataSize;
3132 pipelineCacheInfo.pInitialData = initialData;
3133 VkResult err =
df->vkCreatePipelineCache(
dev, &pipelineCacheInfo,
nullptr, &
pipelineCache);
3134 if (err != VK_SUCCESS) {
3135 qWarning(
"Failed to create pipeline cache: %d", err);
3145 QVarLengthArray<VkDescriptorBufferInfo, 8> bufferInfos;
3146 using ArrayOfImageDesc = QVarLengthArray<VkDescriptorImageInfo, 8>;
3147 QVarLengthArray<ArrayOfImageDesc, 8> imageInfos;
3148 QVarLengthArray<VkWriteDescriptorSet, 12> writeInfos;
3149 QVarLengthArray<QPair<int, int>, 12> infoIndices;
3151 const bool updateAll = descSetIdx < 0;
3152 int frameSlot = updateAll ? 0 : descSetIdx;
3154 for (
int i = 0, ie = srbD->sortedBindings.size();
i != ie; ++
i) {
3158 VkWriteDescriptorSet writeInfo = {};
3159 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3160 writeInfo.dstSet = srbD->descSets[frameSlot];
3161 writeInfo.dstBinding = uint32_t(
b->binding);
3162 writeInfo.descriptorCount = 1;
3164 int bufferInfoIndex = -1;
3165 int imageInfoIndex = -1;
3170 writeInfo.descriptorType =
b->u.ubuf.hasDynamicOffset ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
3171 : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3174 bd.ubuf.id = bufD->m_id;
3175 bd.ubuf.generation = bufD->generation;
3176 VkDescriptorBufferInfo bufInfo;
3177 bufInfo.buffer = bufD->m_type ==
QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
3178 bufInfo.offset =
b->u.ubuf.offset;
3179 bufInfo.range =
b->u.ubuf.maybeSize ?
b->u.ubuf.maybeSize : bufD->m_size;
3182 bufferInfoIndex = bufferInfos.size();
3183 bufferInfos.append(bufInfo);
3189 writeInfo.descriptorCount =
data->count;
3190 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
3191 ArrayOfImageDesc imageInfo(
data->count);
3192 for (
int elem = 0; elem <
data->count; ++elem) {
3195 bd.stex.d[elem].texId = texD->m_id;
3196 bd.stex.d[elem].texGeneration = texD->generation;
3197 bd.stex.d[elem].samplerId = samplerD->m_id;
3198 bd.stex.d[elem].samplerGeneration = samplerD->generation;
3199 imageInfo[elem].sampler = samplerD->sampler;
3200 imageInfo[elem].imageView = texD->imageView;
3201 imageInfo[elem].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3203 bd.stex.count =
data->count;
3204 imageInfoIndex = imageInfos.size();
3205 imageInfos.append(imageInfo);
3211 writeInfo.descriptorCount =
data->count;
3212 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3213 ArrayOfImageDesc imageInfo(
data->count);
3214 for (
int elem = 0; elem <
data->count; ++elem) {
3216 bd.stex.d[elem].texId = texD->m_id;
3217 bd.stex.d[elem].texGeneration = texD->generation;
3218 bd.stex.d[elem].samplerId = 0;
3219 bd.stex.d[elem].samplerGeneration = 0;
3220 imageInfo[elem].sampler = VK_NULL_HANDLE;
3221 imageInfo[elem].imageView = texD->imageView;
3222 imageInfo[elem].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3224 bd.stex.count =
data->count;
3225 imageInfoIndex = imageInfos.size();
3226 imageInfos.append(imageInfo);
3232 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
3233 bd.stex.d[0].texId = 0;
3234 bd.stex.d[0].texGeneration = 0;
3235 bd.stex.d[0].samplerId = samplerD->m_id;
3236 bd.stex.d[0].samplerGeneration = samplerD->generation;
3237 ArrayOfImageDesc imageInfo(1);
3238 imageInfo[0].sampler = samplerD->sampler;
3239 imageInfo[0].imageView = VK_NULL_HANDLE;
3240 imageInfo[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
3241 imageInfoIndex = imageInfos.size();
3242 imageInfos.append(imageInfo);
3250 VkImageView
view = texD->perLevelImageViewForLoadStore(
b->u.simage.level);
3252 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
3253 bd.simage.id = texD->m_id;
3254 bd.simage.generation = texD->generation;
3255 ArrayOfImageDesc imageInfo(1);
3256 imageInfo[0].sampler = VK_NULL_HANDLE;
3257 imageInfo[0].imageView =
view;
3258 imageInfo[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
3259 imageInfoIndex = imageInfos.size();
3260 imageInfos.append(imageInfo);
3269 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3270 bd.sbuf.id = bufD->m_id;
3271 bd.sbuf.generation = bufD->generation;
3272 VkDescriptorBufferInfo bufInfo;
3273 bufInfo.buffer = bufD->m_type ==
QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
3274 bufInfo.offset =
b->u.ubuf.offset;
3275 bufInfo.range =
b->u.ubuf.maybeSize ?
b->u.ubuf.maybeSize : bufD->m_size;
3276 bufferInfoIndex = bufferInfos.size();
3277 bufferInfos.append(bufInfo);
3284 writeInfos.append(writeInfo);
3285 infoIndices.append({ bufferInfoIndex, imageInfoIndex });
3290 for (
int i = 0, writeInfoCount = writeInfos.size();
i < writeInfoCount; ++
i) {
3291 const int bufferInfoIndex = infoIndices[
i].first;
3292 const int imageInfoIndex = infoIndices[
i].second;
3293 if (bufferInfoIndex >= 0)
3294 writeInfos[
i].pBufferInfo = &bufferInfos[bufferInfoIndex];
3295 else if (imageInfoIndex >= 0)
3296 writeInfos[
i].pImageInfo = imageInfos[imageInfoIndex].constData();
3299 df->vkUpdateDescriptorSets(
dev, uint32_t(writeInfos.size()), writeInfos.constData(), 0,
nullptr);
3304 return (
access & VK_ACCESS_SHADER_WRITE_BIT) != 0
3305 || (
access & VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) != 0
3306 || (
access & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) != 0
3307 || (
access & VK_ACCESS_TRANSFER_WRITE_BIT) != 0
3308 || (
access & VK_ACCESS_HOST_WRITE_BIT) != 0
3309 || (
access & VK_ACCESS_MEMORY_WRITE_BIT) != 0;
3313 VkAccessFlags
access, VkPipelineStageFlags stage)
3324 if (
s.access ==
access &&
s.stage == stage) {
3331 VkBufferMemoryBarrier bufMemBarrier = {};
3332 bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
3333 bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
3334 bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
3335 bufMemBarrier.srcAccessMask =
s.access;
3336 bufMemBarrier.dstAccessMask =
access;
3337 bufMemBarrier.buffer = bufD->buffers[slot];
3338 bufMemBarrier.size = VK_WHOLE_SIZE;
3342 cmd.
args.bufferBarrier.srcStageMask =
s.stage;
3343 cmd.
args.bufferBarrier.dstStageMask = stage;
3344 cmd.
args.bufferBarrier.count = 1;
3345 cmd.
args.bufferBarrier.index = cbD->
pools.bufferBarrier.size();
3346 cbD->
pools.bufferBarrier.append(bufMemBarrier);
3353 VkImageLayout
layout, VkAccessFlags
access, VkPipelineStageFlags stage)
3363 VkImageMemoryBarrier barrier = {};
3364 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
3366 barrier.subresourceRange.baseMipLevel = 0;
3367 barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
3368 barrier.subresourceRange.baseArrayLayer = 0;
3369 barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
3370 barrier.oldLayout =
s.layout;
3371 barrier.newLayout =
layout;
3372 barrier.srcAccessMask =
s.access;
3373 barrier.dstAccessMask =
access;
3374 barrier.image = texD->image;
3376 VkPipelineStageFlags srcStage =
s.stage;
3379 srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
3383 cmd.
args.imageBarrier.srcStageMask = srcStage;
3384 cmd.
args.imageBarrier.dstStageMask = stage;
3385 cmd.
args.imageBarrier.count = 1;
3386 cmd.
args.imageBarrier.index = cbD->
pools.imageBarrier.size();
3387 cbD->
pools.imageBarrier.append(barrier);
3398 VkImageMemoryBarrier barrier = {};
3399 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
3400 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
3401 barrier.subresourceRange.baseMipLevel = 0;
3402 barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
3403 barrier.subresourceRange.baseArrayLayer = 0;
3404 barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
3405 barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
3406 barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
3407 barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
3408 barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
3409 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
3410 barrier.image = rbD->image;
3412 const VkPipelineStageFlags
stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
3413 | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
3419 cmd.
args.imageBarrier.count = 1;
3420 cmd.
args.imageBarrier.index = cbD->
pools.imageBarrier.size();
3421 cbD->
pools.imageBarrier.append(barrier);
3425 VkImageLayout oldLayout, VkImageLayout newLayout,
3426 VkAccessFlags srcAccess, VkAccessFlags dstAccess,
3427 VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage,
3428 int startLayer,
int layerCount,
3429 int startLevel,
int levelCount)
3432 VkImageMemoryBarrier barrier = {};
3433 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
3434 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3435 barrier.subresourceRange.baseMipLevel = uint32_t(startLevel);
3436 barrier.subresourceRange.levelCount = uint32_t(levelCount);
3437 barrier.subresourceRange.baseArrayLayer = uint32_t(startLayer);
3438 barrier.subresourceRange.layerCount = uint32_t(layerCount);
3439 barrier.oldLayout = oldLayout;
3440 barrier.newLayout = newLayout;
3441 barrier.srcAccessMask = srcAccess;
3442 barrier.dstAccessMask = dstAccess;
3443 barrier.image =
image;
3447 cmd.
args.imageBarrier.srcStageMask = srcStage;
3448 cmd.
args.imageBarrier.dstStageMask = dstStage;
3449 cmd.
args.imageBarrier.count = 1;
3450 cmd.
args.imageBarrier.index = cbD->
pools.imageBarrier.size();
3451 cbD->
pools.imageBarrier.append(barrier);
3456 VkDeviceSize
size = 0;
3459 if (imageSizeBytes > 0)
3466 size_t *curOfs,
void *mp,
3471 const void *
src =
nullptr;
3475 VkBufferImageCopy copyInfo = {};
3476 copyInfo.bufferOffset = *curOfs;
3477 copyInfo.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3478 copyInfo.imageSubresource.mipLevel = uint32_t(
level);
3479 copyInfo.imageSubresource.baseArrayLayer = is3D ? 0 : uint32_t(
layer);
3480 copyInfo.imageSubresource.layerCount = 1;
3481 copyInfo.imageExtent.depth = 1;
3483 copyInfo.imageOffset.z = uint32_t(
layer);
3485 copyInfo.imageOffset.y = uint32_t(
layer);
3490 if (!
image.isNull()) {
3491 copySizeBytes = imageSizeBytes =
image.sizeInBytes();
3498 copyInfo.bufferRowLength = uint32_t(
image.bytesPerLine() / bpc);
3508 src =
image.constBits() + sy *
image.bytesPerLine() + sx * bpc;
3509 copySizeBytes =
size.height() *
image.bytesPerLine();
3515 copySizeBytes =
image.sizeInBytes();
3517 copyInfo.bufferRowLength = uint32_t(
image.bytesPerLine() / bpc);
3520 copyInfo.imageOffset.x = dp.x();
3521 copyInfo.imageOffset.y = dp.y();
3522 copyInfo.imageExtent.width = uint32_t(
size.width());
3523 copyInfo.imageExtent.height = uint32_t(
size.height());
3524 copyInfos->append(copyInfo);
3526 copySizeBytes = imageSizeBytes = rawData.
size();
3530 const int subresh =
size.height();
3534 const int h =
size.height();
3538 copyInfo.imageOffset.x =
aligned(dp.x(), blockDim.width());
3539 copyInfo.imageOffset.y =
aligned(dp.y(), blockDim.height());
3542 copyInfo.imageExtent.width = uint32_t(dp.x() +
w == subresw ?
w :
aligned(
w, blockDim.width()));
3543 copyInfo.imageExtent.height = uint32_t(dp.y() +
h == subresh ?
h :
aligned(
h, blockDim.height()));
3544 copyInfos->append(copyInfo);
3545 }
else if (!rawData.
isEmpty()) {
3546 copySizeBytes = imageSizeBytes = rawData.
size();
3553 copyInfo.bufferRowLength = subresDesc.
dataStride() / bytesPerPixel;
3557 copyInfo.imageOffset.x = dp.x();
3558 copyInfo.imageOffset.y = dp.y();
3559 copyInfo.imageExtent.
width = uint32_t(
size.width());
3560 copyInfo.imageExtent.height = uint32_t(
size.height());
3561 copyInfos->append(copyInfo);
3567 memcpy(
reinterpret_cast<char *
>(mp) + *curOfs,
src,
size_t(copySizeBytes));
3574 if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY)
3575 qWarning() <<
"Out of device memory, current allocator statistics are" <<
statistics();
3582 for (
int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
3589 bufD->pendingDynamicUpdates[
i].clear();
3590 bufD->pendingDynamicUpdates[
i].append({ u.
offset, u.
data });
3598 VkBufferCreateInfo bufferInfo = {};
3599 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3602 bufferInfo.size = bufD->m_size;
3603 bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
3605 VmaAllocationCreateInfo allocInfo = {};
3606 allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
3611 if (err == VK_SUCCESS) {
3614 qWarning(
"Failed to create staging buffer of size %u: %d", bufD->m_size, err);
3623 if (err != VK_SUCCESS) {
3624 qWarning(
"Failed to map buffer: %d", err);
3632 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
3634 VkBufferCopy copyInfo = {};
3635 copyInfo.srcOffset = u.
offset;
3636 copyInfo.dstOffset = u.
offset;
3642 cmd.
args.copyBuffer.dst = bufD->buffers[0];
3643 cmd.
args.copyBuffer.desc = copyInfo;
3671 if (err == VK_SUCCESS) {
3687 readback.result = u.
result;
3690 VkBufferCreateInfo bufferInfo = {};
3691 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3692 bufferInfo.size = readback.byteSize;
3693 bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3695 VmaAllocationCreateInfo allocInfo = {};
3696 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
3700 if (err == VK_SUCCESS) {
3703 qWarning(
"Failed to create readback buffer of size %u: %d", readback.byteSize, err);
3708 trackedBufferBarrier(cbD, bufD, 0, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
3710 VkBufferCopy copyInfo = {};
3711 copyInfo.srcOffset = u.
offset;
3716 cmd.
args.copyBuffer.src = bufD->buffers[0];
3717 cmd.
args.copyBuffer.dst = readback.stagingBuf;
3718 cmd.
args.copyBuffer.desc = copyInfo;
3727 for (
int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
3732 VkDeviceSize stagingSize = 0;
3741 VkBufferCreateInfo bufferInfo = {};
3742 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3743 bufferInfo.size = stagingSize;
3744 bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
3746 VmaAllocationCreateInfo allocInfo = {};
3747 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
3752 if (err != VK_SUCCESS) {
3753 qWarning(
"Failed to create image staging buffer of size %d: %d",
int(stagingSize), err);
3764 if (err != VK_SUCCESS) {
3765 qWarning(
"Failed to map image data: %d", err);
3776 subresDesc, &curOfs, mp, ©Infos);
3784 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
3789 cmd.
args.copyBufferToImage.dst = utexD->image;
3790 cmd.
args.copyBufferToImage.dstLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
3791 cmd.
args.copyBufferToImage.count = copyInfos.size();
3792 cmd.
args.copyBufferToImage.bufferImageCopyIndex = cbD->
pools.bufferImageCopy.size();
3793 cbD->
pools.bufferImageCopy.append(copyInfos.constData(), copyInfos.size());
3812 qWarning(
"Texture copy with matching source and destination is not supported");
3820 VkImageCopy region = {};
3821 region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3823 region.srcSubresource.baseArrayLayer = srcIs3D ? 0 : uint32_t(u.
desc.
sourceLayer());
3824 region.srcSubresource.layerCount = 1;
3831 region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3834 region.dstSubresource.layerCount = 1;
3843 region.extent.width = uint32_t(copySize.width());
3844 region.extent.height = uint32_t(copySize.height());
3845 region.extent.depth = 1;
3848 VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
3850 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
3854 cmd.
args.copyImage.src = srcD->image;
3855 cmd.
args.copyImage.srcLayout = srcD->usageState.layout;
3856 cmd.
args.copyImage.dst = dstD->image;
3857 cmd.
args.copyImage.dstLayout = dstD->usageState.layout;
3858 cmd.
args.copyImage.desc = region;
3864 readback.desc = u.
rb;
3865 readback.result = u.
result;
3871 if (texD->samples > VK_SAMPLE_COUNT_1_BIT) {
3872 qWarning(
"Multisample texture cannot be read back");
3876 readback.pixelSize =
q->sizeForMipLevel(u.
rb.
level(), texD->m_pixelSize);
3877 readback.format = texD->m_format;
3882 if (!swapChainD->supportsReadback) {
3883 qWarning(
"Swapchain does not support readback");
3886 readback.pixelSize = swapChainD->pixelSize;
3894 textureFormatInfo(readback.format, readback.pixelSize,
nullptr, &readback.byteSize,
nullptr);
3897 VkBufferCreateInfo bufferInfo = {};
3898 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3899 bufferInfo.size = readback.byteSize;
3900 bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3902 VmaAllocationCreateInfo allocInfo = {};
3903 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
3907 if (err == VK_SUCCESS) {
3910 qWarning(
"Failed to create readback buffer of size %u: %d", readback.byteSize, err);
3916 VkBufferImageCopy copyDesc = {};
3917 copyDesc.bufferOffset = 0;
3918 copyDesc.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3919 copyDesc.imageSubresource.mipLevel = uint32_t(u.
rb.
level());
3920 copyDesc.imageSubresource.baseArrayLayer = is3D ? 0 : uint32_t(u.
rb.
layer());
3921 copyDesc.imageSubresource.layerCount = 1;
3923 copyDesc.imageOffset.z = u.
rb.
layer();
3924 copyDesc.imageExtent.width = uint32_t(readback.pixelSize.width());
3925 copyDesc.imageExtent.height = uint32_t(readback.pixelSize.height());
3926 copyDesc.imageExtent.depth = 1;
3930 VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
3933 cmd.
args.copyImageToBuffer.src = texD->image;
3934 cmd.
args.copyImageToBuffer.srcLayout = texD->usageState.layout;
3935 cmd.
args.copyImageToBuffer.dst = readback.stagingBuf;
3936 cmd.
args.copyImageToBuffer.desc = copyDesc;
3943 qWarning(
"Attempted to read back undefined swapchain image content, "
3944 "results are undefined. (do a render pass first)");
3947 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3948 VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT,
3949 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3958 cmd.
args.copyImageToBuffer.srcLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
3959 cmd.
args.copyImageToBuffer.dst = readback.stagingBuf;
3960 cmd.
args.copyImageToBuffer.desc = copyDesc;
3971 VkImageLayout origLayout = utexD->usageState.layout;
3972 VkAccessFlags origAccess = utexD->usageState.access;
3973 VkPipelineStageFlags origStage = utexD->usageState.stage;
3975 origStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
3977 for (
int layer = 0;
layer < (isCube ? 6 : (isArray ?
qMax(0, utexD->m_arraySize) : 1)); ++
layer) {
3978 int w = utexD->m_pixelSize.width();
3979 int h = utexD->m_pixelSize.height();
3980 int depth = is3D ?
qMax(1, utexD->m_depth) : 1;
3984 origLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3985 origAccess, VK_ACCESS_TRANSFER_READ_BIT,
3986 origStage, VK_PIPELINE_STAGE_TRANSFER_BIT,
3991 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3992 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
3993 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
3999 origLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4000 origAccess, VK_ACCESS_TRANSFER_WRITE_BIT,
4001 origStage, VK_PIPELINE_STAGE_TRANSFER_BIT,
4005 VkImageBlit region = {};
4006 region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
4007 region.srcSubresource.mipLevel = uint32_t(
level) - 1;
4008 region.srcSubresource.baseArrayLayer = uint32_t(
layer);
4009 region.srcSubresource.layerCount = 1;
4011 region.srcOffsets[1].x =
qMax(1,
w);
4012 region.srcOffsets[1].y =
qMax(1,
h);
4013 region.srcOffsets[1].z =
qMax(1,
depth);
4015 region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
4016 region.dstSubresource.mipLevel = uint32_t(
level);
4017 region.dstSubresource.baseArrayLayer = uint32_t(
layer);
4018 region.dstSubresource.layerCount = 1;
4020 region.dstOffsets[1].x =
qMax(1,
w >> 1);
4021 region.dstOffsets[1].y =
qMax(1,
h >> 1);
4022 region.dstOffsets[1].z =
qMax(1,
depth >> 1);
4026 cmd.
args.blitImage.src = utexD->image;
4027 cmd.
args.blitImage.srcLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
4028 cmd.
args.blitImage.dst = utexD->image;
4029 cmd.
args.blitImage.dstLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
4030 cmd.
args.blitImage.filter = VK_FILTER_LINEAR;
4031 cmd.
args.blitImage.desc = region;
4038 if (utexD->mipLevelCount > 1) {
4040 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, origLayout,
4041 VK_ACCESS_TRANSFER_READ_BIT, origAccess,
4042 VK_PIPELINE_STAGE_TRANSFER_BIT, origStage,
4044 0,
int(utexD->mipLevelCount) - 1);
4046 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, origLayout,
4047 VK_ACCESS_TRANSFER_WRITE_BIT, origAccess,
4048 VK_PIPELINE_STAGE_TRANSFER_BIT, origStage,
4050 int(utexD->mipLevelCount) - 1, 1);
4062 if (bufD->pendingDynamicUpdates[slot].isEmpty())
4072 if (err != VK_SUCCESS) {
4073 qWarning(
"Failed to map buffer: %d", err);
4076 quint32 changeBegin = UINT32_MAX;
4079 memcpy(
static_cast<char *
>(
p) + u.offset, u.data.constData(), u.data.size());
4080 if (u.offset < changeBegin)
4081 changeBegin = u.offset;
4082 if (u.offset + u.data.size() > changeEnd)
4083 changeEnd = u.offset + u.data.size();
4085 if (changeBegin < UINT32_MAX && changeBegin < changeEnd)
4089 bufD->pendingDynamicUpdates[slot].clear();
4102 df->vkDestroyImageView(dev, e.
renderBuffer.imageView,
nullptr);
4103 df->vkDestroyImage(dev, e.
renderBuffer.image,
nullptr);
4109 df->vkDestroyImageView(dev, e.
texture.imageView,
nullptr);
4115 df->vkDestroyImageView(dev, e.
texture.extraImageViews[
i],
nullptr);
4121 df->vkDestroySampler(dev, e.
sampler.sampler,
nullptr);
4186 if (forced ||
currentFrameSlot == readback.activeFrameSlot || readback.activeFrameSlot < 0) {
4187 readback.result->format = readback.format;
4188 readback.result->pixelSize = readback.pixelSize;
4192 if (err == VK_SUCCESS &&
p) {
4193 readback.result->data.resize(
int(readback.byteSize));
4194 memcpy(readback.result->data.data(),
p, readback.byteSize);
4197 qWarning(
"Failed to map texture readback buffer of size %u: %d", readback.byteSize, err);
4202 if (readback.result->completed)
4203 completedCallbacks.append(readback.result->completed);
4211 if (forced ||
currentFrameSlot == readback.activeFrameSlot || readback.activeFrameSlot < 0) {
4215 if (err == VK_SUCCESS &&
p) {
4216 readback.result->data.resize(readback.byteSize);
4217 memcpy(readback.result->data.data(),
p, readback.byteSize);
4220 qWarning(
"Failed to map buffer readback buffer of size %d: %d", readback.byteSize, err);
4225 if (readback.result->completed)
4226 completedCallbacks.append(readback.result->completed);
4232 for (
auto f : completedCallbacks)
4237 VkSampleCountFlagBits
mask;
4241 { VK_SAMPLE_COUNT_1_BIT, 1 },
4242 { VK_SAMPLE_COUNT_2_BIT, 2 },
4243 { VK_SAMPLE_COUNT_4_BIT, 4 },
4244 { VK_SAMPLE_COUNT_8_BIT, 8 },
4245 { VK_SAMPLE_COUNT_16_BIT, 16 },
4246 { VK_SAMPLE_COUNT_32_BIT, 32 },
4247 { VK_SAMPLE_COUNT_64_BIT, 64 }
4253 VkSampleCountFlags
color = limits->framebufferColorSampleCounts;
4254 VkSampleCountFlags
depth = limits->framebufferDepthSampleCounts;
4255 VkSampleCountFlags
stencil = limits->framebufferStencilSampleCounts;
4259 if ((
color & qvk_sampleCount.mask)
4260 && (
depth & qvk_sampleCount.mask)
4261 && (
stencil & qvk_sampleCount.mask))
4263 result.append(qvk_sampleCount.count);
4275 if (qvk_sampleCount.count ==
s)
4276 return qvk_sampleCount.mask;
4279 Q_UNREACHABLE_RETURN(VK_SAMPLE_COUNT_1_BIT);
4300 df->vkCmdCopyBuffer(cbD->
cb, cmd.
args.copyBuffer.src, cmd.
args.copyBuffer.dst,
4301 1, &cmd.
args.copyBuffer.desc);
4304 df->vkCmdCopyBufferToImage(cbD->
cb, cmd.
args.copyBufferToImage.src, cmd.
args.copyBufferToImage.dst,
4305 cmd.
args.copyBufferToImage.dstLayout,
4306 uint32_t(cmd.
args.copyBufferToImage.count),
4307 cbD->
pools.bufferImageCopy.constData() + cmd.
args.copyBufferToImage.bufferImageCopyIndex);
4310 df->vkCmdCopyImage(cbD->
cb, cmd.
args.copyImage.src, cmd.
args.copyImage.srcLayout,
4311 cmd.
args.copyImage.dst, cmd.
args.copyImage.dstLayout,
4312 1, &cmd.
args.copyImage.desc);
4315 df->vkCmdCopyImageToBuffer(cbD->
cb, cmd.
args.copyImageToBuffer.src, cmd.
args.copyImageToBuffer.srcLayout,
4316 cmd.
args.copyImageToBuffer.dst,
4317 1, &cmd.
args.copyImageToBuffer.desc);
4320 df->vkCmdPipelineBarrier(cbD->
cb, cmd.
args.imageBarrier.srcStageMask, cmd.
args.imageBarrier.dstStageMask,
4321 0, 0,
nullptr, 0,
nullptr,
4322 cmd.
args.imageBarrier.count, cbD->
pools.imageBarrier.constData() + cmd.
args.imageBarrier.index);
4325 df->vkCmdPipelineBarrier(cbD->
cb, cmd.
args.bufferBarrier.srcStageMask, cmd.
args.bufferBarrier.dstStageMask,
4327 cmd.
args.bufferBarrier.count, cbD->
pools.bufferBarrier.constData() + cmd.
args.bufferBarrier.index,
4331 df->vkCmdBlitImage(cbD->
cb, cmd.
args.blitImage.src, cmd.
args.blitImage.srcLayout,
4332 cmd.
args.blitImage.dst, cmd.
args.blitImage.dstLayout,
4333 1, &cmd.
args.blitImage.desc,
4334 cmd.
args.blitImage.filter);
4337 cmd.
args.beginRenderPass.desc.pClearValues = cbD->
pools.clearValue.constData() + cmd.
args.beginRenderPass.clearValueIndex;
4338 df->vkCmdBeginRenderPass(cbD->
cb, &cmd.
args.beginRenderPass.desc,
4339 cmd.
args.beginRenderPass.useSecondaryCb ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
4340 : VK_SUBPASS_CONTENTS_INLINE);
4343 df->vkCmdEndRenderPass(cbD->
cb);
4346 df->vkCmdBindPipeline(cbD->
cb, cmd.
args.bindPipeline.bindPoint, cmd.
args.bindPipeline.pipeline);
4350 const uint32_t *
offsets =
nullptr;
4351 if (cmd.
args.bindDescriptorSet.dynamicOffsetCount > 0)
4352 offsets = cbD->
pools.dynamicOffset.constData() + cmd.
args.bindDescriptorSet.dynamicOffsetIndex;
4353 df->vkCmdBindDescriptorSets(cbD->
cb, cmd.
args.bindDescriptorSet.bindPoint,
4354 cmd.
args.bindDescriptorSet.pipelineLayout,
4355 0, 1, &cmd.
args.bindDescriptorSet.descSet,
4356 uint32_t(cmd.
args.bindDescriptorSet.dynamicOffsetCount),
4361 df->vkCmdBindVertexBuffers(cbD->
cb, uint32_t(cmd.
args.bindVertexBuffer.startBinding),
4362 uint32_t(cmd.
args.bindVertexBuffer.count),
4363 cbD->
pools.vertexBuffer.constData() + cmd.
args.bindVertexBuffer.vertexBufferIndex,
4364 cbD->
pools.vertexBufferOffset.constData() + cmd.
args.bindVertexBuffer.vertexBufferOffsetIndex);
4367 df->vkCmdBindIndexBuffer(cbD->
cb, cmd.
args.bindIndexBuffer.buf,
4368 cmd.
args.bindIndexBuffer.ofs, cmd.
args.bindIndexBuffer.type);
4371 df->vkCmdSetViewport(cbD->
cb, 0, 1, &cmd.
args.setViewport.viewport);
4374 df->vkCmdSetScissor(cbD->
cb, 0, 1, &cmd.
args.setScissor.scissor);
4377 df->vkCmdSetBlendConstants(cbD->
cb, cmd.
args.setBlendConstants.c);
4380 df->vkCmdSetStencilReference(cbD->
cb, VK_STENCIL_FRONT_AND_BACK, cmd.
args.setStencilRef.ref);
4383 df->vkCmdDraw(cbD->
cb, cmd.
args.draw.vertexCount, cmd.
args.draw.instanceCount,
4384 cmd.
args.draw.firstVertex, cmd.
args.draw.firstInstance);
4387 df->vkCmdDrawIndexed(cbD->
cb, cmd.
args.drawIndexed.indexCount, cmd.
args.drawIndexed.instanceCount,
4388 cmd.
args.drawIndexed.firstIndex, cmd.
args.drawIndexed.vertexOffset,
4389 cmd.
args.drawIndexed.firstInstance);
4392#ifdef VK_EXT_debug_utils
4393 cmd.
args.debugMarkerBegin.label.pLabelName =
4394 cbD->
pools.debugMarkerData[cmd.
args.debugMarkerBegin.labelNameIndex].constData();
4395 vkCmdBeginDebugUtilsLabelEXT(cbD->
cb, &cmd.
args.debugMarkerBegin.label);
4399#ifdef VK_EXT_debug_utils
4400 vkCmdEndDebugUtilsLabelEXT(cbD->
cb);
4404#ifdef VK_EXT_debug_utils
4405 cmd.
args.debugMarkerInsert.label.pLabelName =
4406 cbD->
pools.debugMarkerData[cmd.
args.debugMarkerInsert.labelNameIndex].constData();
4407 vkCmdInsertDebugUtilsLabelEXT(cbD->
cb, &cmd.
args.debugMarkerInsert.label);
4414 df->vkCmdDispatch(cbD->
cb, uint32_t(cmd.
args.dispatch.x), uint32_t(cmd.
args.dispatch.y), uint32_t(cmd.
args.dispatch.z));
4417 df->vkCmdExecuteCommands(cbD->
cb, 1, &cmd.
args.executeSecondary.cb);
4429 return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
4431 return VK_ACCESS_INDEX_READ_BIT;
4433 return VK_ACCESS_UNIFORM_READ_BIT;
4435 return VK_ACCESS_SHADER_READ_BIT;
4437 return VK_ACCESS_SHADER_WRITE_BIT;
4439 return VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
4451 return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
4453 return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
4455 return VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
4457 return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
4459 return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
4461 return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
4463 return VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
4483 return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4485 return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4487 return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
4491 return VK_IMAGE_LAYOUT_GENERAL;
4496 return VK_IMAGE_LAYOUT_GENERAL;
4503 return VK_ACCESS_SHADER_READ_BIT;
4505 return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
4507 return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
4509 return VK_ACCESS_SHADER_READ_BIT;
4511 return VK_ACCESS_SHADER_WRITE_BIT;
4513 return VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
4525 return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
4527 return VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
4529 return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
4531 return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
4533 return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
4535 return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
4537 return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
4539 return VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
4565 if (u.
access == newAccess && u.
stage == newStage) {
4595 if (tracker.isEmpty())
4598 for (
auto it = tracker.cbeginBuffers(), itEnd = tracker.cendBuffers();
it != itEnd; ++
it) {
4605 if (
s.access ==
access &&
s.stage == stage) {
4609 VkBufferMemoryBarrier bufMemBarrier = {};
4610 bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
4611 bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4612 bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4613 bufMemBarrier.srcAccessMask =
s.access;
4614 bufMemBarrier.dstAccessMask =
access;
4615 bufMemBarrier.buffer = bufD->buffers[
it->slot];
4616 bufMemBarrier.size = VK_WHOLE_SIZE;
4617 df->vkCmdPipelineBarrier(cbD->
cb,
s.stage, stage, 0,
4623 for (
auto it = tracker.cbeginTextures(), itEnd = tracker.cendTextures();
it != itEnd; ++
it) {
4633 VkImageMemoryBarrier barrier = {};
4634 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
4636 barrier.subresourceRange.baseMipLevel = 0;
4637 barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
4638 barrier.subresourceRange.baseArrayLayer = 0;
4639 barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
4640 barrier.oldLayout =
s.layout;
4641 barrier.newLayout =
layout;
4642 barrier.srcAccessMask =
s.access;
4643 barrier.dstAccessMask =
access;
4644 barrier.image = texD->image;
4645 VkPipelineStageFlags srcStage =
s.stage;
4648 srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
4649 df->vkCmdPipelineBarrier(cbD->
cb, srcStage, stage, 0,
4662 qWarning(
"Physical device surface queries not available");
4699 if (
m.isIdentity()) {
4702 0.0f, -1.0f, 0.0f, 0.0f,
4703 0.0f, 0.0f, 0.5f, 0.5f,
4704 0.0f, 0.0f, 0.0f, 1.0f);
4730 VkFormatProperties
props;
4731 f->vkGetPhysicalDeviceFormatProperties(
physDev, vkformat, &
props);
4732 return (
props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0;
4743 return caps.debugUtils;
4749 return caps.vertexAttribDivisor;
4763 return caps.compute;
4765 return caps.wideLines;
4797 return caps.texture3DSliceAs2D;
4801 return caps.tessellation;
4803 return caps.geometryShader;
4807 return caps.nonFillPolygonMode;
4819 return caps.multiView;
4823 return caps.renderPass2KHR &&
caps.depthStencilResolveKHR;
4825 Q_UNREACHABLE_RETURN(
false);
4857 return int(qMin<uint32_t>(INT_MAX,
physDevProperties.limits.maxUniformBufferRange));
4863 Q_UNREACHABLE_RETURN(0);
4882 VmaBudget budgets[VK_MAX_MEMORY_HEAPS];
4886 for (uint32_t
i = 0;
i <
count; ++
i) {
4887 const VmaStatistics &stats(budgets[
i].
statistics);
4888 result.blockCount += stats.blockCount;
4889 result.allocCount += stats.allocationCount;
4890 result.usedBytes += stats.allocationBytes;
4891 result.unusedBytes += stats.blockBytes - stats.allocationBytes;
4935 if (err != VK_SUCCESS) {
4936 qCDebug(QRHI_LOG_INFO,
"Failed to get pipeline cache data size: %d", err);
4940 const size_t dataOffset =
headerSize + VK_UUID_SIZE;
4943 if (err != VK_SUCCESS) {
4944 qCDebug(QRHI_LOG_INFO,
"Failed to get pipeline cache data of %d bytes: %d",
int(
dataSize), err);
4955 header.uuidSize = VK_UUID_SIZE;
4970 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size");
4977 if (
header.rhiId != rhiId) {
4978 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
4983 if (
header.arch != arch) {
4984 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
4989 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: driverVersion does not match (%u, %u)",
4994 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: vendorID does not match (%u, %u)",
4999 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: deviceID does not match (%u, %u)",
5003 if (
header.uuidSize != VK_UUID_SIZE) {
5004 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: VK_UUID_SIZE does not match (%u, %u)",
5010 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob, no uuid");
5014 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: pipelineCacheUUID does not match");
5018 const size_t dataOffset =
headerSize + VK_UUID_SIZE;
5020 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob, data missing");
5030 qCDebug(QRHI_LOG_INFO,
"Created pipeline cache with initial data of %d bytes",
5033 qCDebug(QRHI_LOG_INFO,
"Failed to create pipeline cache with initial data specified");
5038 int sampleCount, QRhiRenderBuffer::Flags
flags,
5045 const QSize &pixelSize,
int depth,
int arraySize,
5046 int sampleCount, QRhiTexture::Flags
flags)
5055 return new QVkSampler(
this, magFilter, minFilter, mipmapMode, u,
v,
w);
5059 QRhiTextureRenderTarget::Flags
flags)
5092 cmd.
args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
5093 cmd.
args.bindPipeline.pipeline = psD->pipeline;
5105 int dynamicOffsetCount,
5116 srb = gfxPsD->m_shaderResourceBindings;
5118 srb = compPsD->m_shaderResourceBindings;
5123 auto &descSetBd(srbD->boundResourceData[descSetIdx]);
5124 bool rewriteDescSet =
false;
5128 for (
int i = 0, ie = srbD->sortedBindings.size();
i != ie; ++
i) {
5149 if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
5150 rewriteDescSet =
true;
5151 bd.ubuf.id = bufD->m_id;
5152 bd.ubuf.generation = bufD->generation;
5161 if (bd.stex.count !=
data->count) {
5163 rewriteDescSet =
true;
5165 for (
int elem = 0; elem <
data->count; ++elem) {
5180 const quint64 texId = texD ? texD->m_id : 0;
5181 const uint texGen = texD ? texD->generation : 0;
5182 const quint64 samplerId = samplerD ? samplerD->m_id : 0;
5183 const uint samplerGen = samplerD ? samplerD->generation : 0;
5184 if (texGen != bd.stex.d[elem].texGeneration
5185 || texId != bd.stex.d[elem].texId
5186 || samplerGen != bd.stex.d[elem].samplerGeneration
5187 || samplerId != bd.stex.d[elem].samplerId)
5189 rewriteDescSet =
true;
5190 bd.stex.d[elem].texId = texId;
5191 bd.stex.d[elem].texGeneration = texGen;
5192 bd.stex.d[elem].samplerId = samplerId;
5193 bd.stex.d[elem].samplerGeneration = samplerGen;
5216 if (texD->generation != bd.simage.generation || texD->m_id != bd.simage.id) {
5217 rewriteDescSet =
true;
5218 bd.simage.id = texD->m_id;
5219 bd.simage.generation = texD->generation;
5245 if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
5246 rewriteDescSet =
true;
5247 bd.sbuf.id = bufD->m_id;
5248 bd.sbuf.generation = bufD->generation;
5264 const bool forceRebind = (srbD->hasSlottedResource && cbD->
currentDescSetSlot != descSetIdx) || srbD->hasDynamicOffset;
5268 if (forceRebind || rewriteDescSet || srbChanged || cbD->
currentSrbGeneration != srbD->generation) {
5269 QVarLengthArray<uint32_t, 4> dynOfs;
5270 if (srbD->hasDynamicOffset) {
5279 for (
int i = 0;
i < dynamicOffsetCount; ++
i) {
5281 if (bindingOffsetPair.first ==
b->binding) {
5282 offset = bindingOffsetPair.second;
5293 gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
5294 gfxPsD ? gfxPsD->layout : compPsD->layout,
5295 0, 1, &srbD->descSets[descSetIdx],
5296 uint32_t(dynOfs.size()),
5297 dynOfs.size() ? dynOfs.constData() :
nullptr);
5301 cmd.
args.bindDescriptorSet.bindPoint = gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS
5302 : VK_PIPELINE_BIND_POINT_COMPUTE;
5303 cmd.
args.bindDescriptorSet.pipelineLayout = gfxPsD ? gfxPsD->layout : compPsD->layout;
5304 cmd.
args.bindDescriptorSet.descSet = srbD->descSets[descSetIdx];
5305 cmd.
args.bindDescriptorSet.dynamicOffsetCount = dynOfs.size();
5306 cmd.
args.bindDescriptorSet.dynamicOffsetIndex = cbD->
pools.dynamicOffset.size();
5307 cbD->
pools.dynamicOffset.append(dynOfs.constData(), dynOfs.size());
5332 bool needsBindVBuf =
false;
5333 for (
int i = 0;
i < bindingCount; ++
i) {
5334 const int inputSlot = startBinding +
i;
5345 needsBindVBuf =
true;
5351 if (needsBindVBuf) {
5352 QVarLengthArray<VkBuffer, 4>
bufs;
5353 QVarLengthArray<VkDeviceSize, 4> ofs;
5354 for (
int i = 0;
i < bindingCount; ++
i) {
5357 bufs.append(bufD->buffers[slot]);
5358 ofs.append(bindings[
i].second);
5366 uint32_t(
bufs.size()),
bufs.constData(), ofs.constData());
5370 cmd.
args.bindVertexBuffer.startBinding = startBinding;
5371 cmd.
args.bindVertexBuffer.count =
bufs.size();
5372 cmd.
args.bindVertexBuffer.vertexBufferIndex = cbD->
pools.vertexBuffer.size();
5373 cbD->
pools.vertexBuffer.append(
bufs.constData(),
bufs.size());
5374 cmd.
args.bindVertexBuffer.vertexBufferOffsetIndex = cbD->
pools.vertexBufferOffset.size();
5375 cbD->
pools.vertexBufferOffset.append(ofs.constData(), ofs.size());
5387 const VkBuffer vkindexbuf = ibufD->buffers[slot];
5389 : VK_INDEX_TYPE_UINT32;
5404 cmd.
args.bindIndexBuffer.buf = vkindexbuf;
5405 cmd.
args.bindIndexBuffer.ofs = indexOffset;
5406 cmd.
args.bindIndexBuffer.type =
type;
5424 if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize,
viewport.viewport(), &
x, &
y, &
w, &
h))
5428 VkViewport *vp = &cmd.
args.setViewport.viewport;
5433 vp->minDepth =
viewport.minDepth();
5434 vp->maxDepth =
viewport.maxDepth();
5447 VkRect2D *
s = &cmd.
args.setScissor.scissor;
5448 qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize,
viewport.viewport(), &
x, &
y, &
w, &
h);
5449 s->offset.x = int32_t(
x);
5450 s->offset.y = int32_t(
y);
5451 s->extent.width = uint32_t(
w);
5452 s->extent.height = uint32_t(
h);
5471 if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.
scissor(), &
x, &
y, &
w, &
h))
5475 VkRect2D *
s = &cmd.
args.setScissor.scissor;
5478 s->extent.width = uint32_t(
w);
5479 s->extent.height = uint32_t(
h);
5495 float constants[] = { float(
c.redF()), float(
c.greenF()), float(
c.blueF()), float(
c.alphaF()) };
5500 cmd.
args.setBlendConstants.c[0] = float(
c.redF());
5501 cmd.
args.setBlendConstants.c[1] = float(
c.greenF());
5502 cmd.
args.setBlendConstants.c[2] = float(
c.blueF());
5503 cmd.
args.setBlendConstants.c[3] = float(
c.alphaF());
5517 cmd.
args.setStencilRef.ref = refValue;
5532 cmd.
args.draw.vertexCount = vertexCount;
5534 cmd.
args.draw.firstVertex = firstVertex;
5535 cmd.
args.draw.firstInstance = firstInstance;
5547 firstIndex, vertexOffset, firstInstance);
5551 cmd.
args.drawIndexed.indexCount = indexCount;
5553 cmd.
args.drawIndexed.firstIndex = firstIndex;
5554 cmd.
args.drawIndexed.vertexOffset = vertexOffset;
5555 cmd.
args.drawIndexed.firstInstance = firstInstance;
5561#ifdef VK_EXT_debug_utils
5565 VkDebugUtilsLabelEXT
label = {};
5566 label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
5575 cmd.
args.debugMarkerBegin.label =
label;
5576 cmd.
args.debugMarkerBegin.labelNameIndex = cbD->
pools.debugMarkerData.size();
5577 cbD->
pools.debugMarkerData.append(
name);
5587#ifdef VK_EXT_debug_utils
5605#ifdef VK_EXT_debug_utils
5609 VkDebugUtilsLabelEXT
label = {};
5610 label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
5619 cmd.
args.debugMarkerInsert.label =
label;
5620 cmd.
args.debugMarkerInsert.labelNameIndex = cbD->
pools.debugMarkerData.size();
5621 cbD->
pools.debugMarkerData.append(msg);
5675 qWarning(
"beginExternal() within a pass is only supported with secondary command buffers. "
5676 "This can be enabled by passing QRhiCommandBuffer::ExternalContent to beginPass().");
5715#ifdef VK_EXT_debug_utils
5719 VkDebugUtilsObjectNameInfoEXT nameInfo = {};
5720 nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
5721 nameInfo.objectType =
type;
5722 nameInfo.objectHandle =
object;
5725 decoratedName +=
'/';
5728 nameInfo.pObjectName = decoratedName.constData();
5729 vkSetDebugUtilsObjectNameEXT(
dev, &nameInfo);
5742 u |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
5744 u |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
5746 u |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
5748 u |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
5749 return VkBufferUsageFlagBits(u);
5756 return VK_FILTER_NEAREST;
5758 return VK_FILTER_LINEAR;
5760 Q_UNREACHABLE_RETURN(VK_FILTER_NEAREST);
5768 return VK_SAMPLER_MIPMAP_MODE_NEAREST;
5770 return VK_SAMPLER_MIPMAP_MODE_NEAREST;
5772 return VK_SAMPLER_MIPMAP_MODE_LINEAR;
5774 Q_UNREACHABLE_RETURN(VK_SAMPLER_MIPMAP_MODE_NEAREST);
5782 return VK_SAMPLER_ADDRESS_MODE_REPEAT;
5784 return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
5786 return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
5788 Q_UNREACHABLE_RETURN(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
5796 return VK_SHADER_STAGE_VERTEX_BIT;
5798 return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
5800 return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
5802 return VK_SHADER_STAGE_FRAGMENT_BIT;
5804 return VK_SHADER_STAGE_COMPUTE_BIT;
5806 return VK_SHADER_STAGE_GEOMETRY_BIT;
5808 Q_UNREACHABLE_RETURN(VK_SHADER_STAGE_VERTEX_BIT);
5816 return VK_FORMAT_R32G32B32A32_SFLOAT;
5818 return VK_FORMAT_R32G32B32_SFLOAT;
5820 return VK_FORMAT_R32G32_SFLOAT;
5822 return VK_FORMAT_R32_SFLOAT;
5824 return VK_FORMAT_R8G8B8A8_UNORM;
5826 return VK_FORMAT_R8G8_UNORM;
5828 return VK_FORMAT_R8_UNORM;
5830 return VK_FORMAT_R32G32B32A32_UINT;
5832 return VK_FORMAT_R32G32B32_UINT;
5834 return VK_FORMAT_R32G32_UINT;
5836 return VK_FORMAT_R32_UINT;
5838 return VK_FORMAT_R32G32B32A32_SINT;
5840 return VK_FORMAT_R32G32B32_SINT;
5842 return VK_FORMAT_R32G32_SINT;
5844 return VK_FORMAT_R32_SINT;
5846 return VK_FORMAT_R16G16B16A16_SFLOAT;
5848 return VK_FORMAT_R16G16B16_SFLOAT;
5850 return VK_FORMAT_R16G16_SFLOAT;
5852 return VK_FORMAT_R16_SFLOAT;
5854 return VK_FORMAT_R16G16B16A16_UINT;
5856 return VK_FORMAT_R16G16B16_UINT;
5858 return VK_FORMAT_R16G16_UINT;
5860 return VK_FORMAT_R16_UINT;
5862 return VK_FORMAT_R16G16B16A16_SINT;
5864 return VK_FORMAT_R16G16B16_SINT;
5866 return VK_FORMAT_R16G16_SINT;
5868 return VK_FORMAT_R16_SINT;
5870 Q_UNREACHABLE_RETURN(VK_FORMAT_R32G32B32A32_SFLOAT);
5878 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
5880 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
5882 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
5884 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
5886 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
5888 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
5890 return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
5892 Q_UNREACHABLE_RETURN(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
5900 return VK_CULL_MODE_NONE;
5902 return VK_CULL_MODE_FRONT_BIT;
5904 return VK_CULL_MODE_BACK_BIT;
5906 Q_UNREACHABLE_RETURN(VK_CULL_MODE_NONE);
5914 return VK_FRONT_FACE_COUNTER_CLOCKWISE;
5916 return VK_FRONT_FACE_CLOCKWISE;
5918 Q_UNREACHABLE_RETURN(VK_FRONT_FACE_COUNTER_CLOCKWISE);
5926 f |= VK_COLOR_COMPONENT_R_BIT;
5928 f |= VK_COLOR_COMPONENT_G_BIT;
5930 f |= VK_COLOR_COMPONENT_B_BIT;
5932 f |= VK_COLOR_COMPONENT_A_BIT;
5933 return VkColorComponentFlags(
f);
5940 return VK_BLEND_FACTOR_ZERO;
5942 return VK_BLEND_FACTOR_ONE;
5944 return VK_BLEND_FACTOR_SRC_COLOR;
5946 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
5948 return VK_BLEND_FACTOR_DST_COLOR;
5950 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
5952 return VK_BLEND_FACTOR_SRC_ALPHA;
5954 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
5956 return VK_BLEND_FACTOR_DST_ALPHA;
5958 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
5960 return VK_BLEND_FACTOR_CONSTANT_COLOR;
5962 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
5964 return VK_BLEND_FACTOR_CONSTANT_ALPHA;
5966 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
5968 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
5970 return VK_BLEND_FACTOR_SRC1_COLOR;
5972 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
5974 return VK_BLEND_FACTOR_SRC1_ALPHA;
5976 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
5978 Q_UNREACHABLE_RETURN(VK_BLEND_FACTOR_ZERO);
5986 return VK_BLEND_OP_ADD;
5988 return VK_BLEND_OP_SUBTRACT;
5990 return VK_BLEND_OP_REVERSE_SUBTRACT;
5992 return VK_BLEND_OP_MIN;
5994 return VK_BLEND_OP_MAX;
5996 Q_UNREACHABLE_RETURN(VK_BLEND_OP_ADD);
6004 return VK_COMPARE_OP_NEVER;
6006 return VK_COMPARE_OP_LESS;
6008 return VK_COMPARE_OP_EQUAL;
6010 return VK_COMPARE_OP_LESS_OR_EQUAL;
6012 return VK_COMPARE_OP_GREATER;
6014 return VK_COMPARE_OP_NOT_EQUAL;
6016 return VK_COMPARE_OP_GREATER_OR_EQUAL;
6018 return VK_COMPARE_OP_ALWAYS;
6020 Q_UNREACHABLE_RETURN(VK_COMPARE_OP_ALWAYS);
6028 return VK_STENCIL_OP_ZERO;
6030 return VK_STENCIL_OP_KEEP;
6032 return VK_STENCIL_OP_REPLACE;
6034 return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
6036 return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
6038 return VK_STENCIL_OP_INVERT;
6040 return VK_STENCIL_OP_INCREMENT_AND_WRAP;
6042 return VK_STENCIL_OP_DECREMENT_AND_WRAP;
6044 Q_UNREACHABLE_RETURN(VK_STENCIL_OP_KEEP);
6052 return VK_POLYGON_MODE_FILL;
6054 return VK_POLYGON_MODE_LINE;
6056 Q_UNREACHABLE_RETURN(VK_POLYGON_MODE_FILL);
6072 return b->u.ubuf.hasDynamicOffset ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
6073 : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6076 return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
6079 return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
6082 return VK_DESCRIPTOR_TYPE_SAMPLER;
6087 return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
6092 return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
6095 Q_UNREACHABLE_RETURN(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
6103 s |= VK_SHADER_STAGE_VERTEX_BIT;
6105 s |= VK_SHADER_STAGE_FRAGMENT_BIT;
6107 s |= VK_SHADER_STAGE_COMPUTE_BIT;
6109 s |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
6111 s |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
6113 s |= VK_SHADER_STAGE_GEOMETRY_BIT;
6114 return VkShaderStageFlags(
s);
6121 return VK_COMPARE_OP_NEVER;
6123 return VK_COMPARE_OP_LESS;
6125 return VK_COMPARE_OP_EQUAL;
6127 return VK_COMPARE_OP_LESS_OR_EQUAL;
6129 return VK_COMPARE_OP_GREATER;
6131 return VK_COMPARE_OP_NOT_EQUAL;
6133 return VK_COMPARE_OP_GREATER_OR_EQUAL;
6135 return VK_COMPARE_OP_ALWAYS;
6137 Q_UNREACHABLE_RETURN(VK_COMPARE_OP_NEVER);
6182 rhiD->releaseQueue.append(e);
6183 rhiD->unregisterResource(
this);
6193 qWarning(
"StorageBuffer cannot be combined with Dynamic");
6199 VkBufferCreateInfo bufferInfo = {};
6200 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
6201 bufferInfo.size = nonZeroSize;
6204 VmaAllocationCreateInfo allocInfo = {};
6211 allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
6214 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
6216 allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
6217 bufferInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
6221 VkResult err = VK_SUCCESS;
6229 if (err != VK_SUCCESS)
6237 if (err != VK_SUCCESS) {
6238 qWarning(
"Failed to create buffer of size %u: %d", nonZeroSize, err);
6239 rhiD->printExtraErrorInfo(err);
6245 rhiD->registerResource(
this);
6256 rhiD->executeBufferHostWritesForSlot(
this,
i);
6262 return { { &
buffers[0] }, 1 };
6275 const int slot = rhiD->currentFrameSlot;
6279 if (err != VK_SUCCESS) {
6280 qWarning(
"Failed to map buffer: %d", err);
6283 return static_cast<char *
>(
p);
6289 const int slot = rhiD->currentFrameSlot;
6322 image = VK_NULL_HANDLE;
6333 rhiD->releaseQueue.append(e);
6334 rhiD->unregisterResource(
this);
6370 vkformat = rhiD->optimalDepthStencilFormat();
6371 if (!rhiD->createTransientImage(
vkformat,
6373 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
6374 VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
6392 rhiD->registerResource(
this);
6447 image = VK_NULL_HANDLE;
6453 rhiD->releaseQueue.append(e);
6454 rhiD->unregisterResource(
this);
6474 VkFormatProperties
props;
6475 rhiD->f->vkGetPhysicalDeviceFormatProperties(rhiD->physDev,
vkformat, &
props);
6476 const bool canSampleOptimal = (
props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
6477 if (!canSampleOptimal) {
6478 qWarning(
"Texture sampling with optimal tiling for format %d not supported",
vkformat);
6498 if (
samples > VK_SAMPLE_COUNT_1_BIT) {
6500 qWarning(
"Cubemap texture cannot be multisample");
6504 qWarning(
"3D texture cannot be multisample");
6508 qWarning(
"Multisample texture cannot have mipmaps");
6512 if (isCube && is3D) {
6513 qWarning(
"Texture cannot be both cube and 3D");
6516 if (isArray && is3D) {
6517 qWarning(
"Texture cannot be both array and 3D");
6520 if (isCube && is1D) {
6521 qWarning(
"Texture cannot be both cube and 1D");
6525 qWarning(
"Texture cannot be both 1D and 3D");
6529 qWarning(
"Texture cannot have a depth of %d when it is not 3D",
m_depth);
6546 *adjustedSize =
size;
6561 VkImageViewCreateInfo viewInfo = {};
6562 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
6563 viewInfo.image =
image;
6564 viewInfo.viewType = isCube
6565 ? VK_IMAGE_VIEW_TYPE_CUBE
6566 : (is3D ? VK_IMAGE_VIEW_TYPE_3D
6567 : (is1D ? (isArray ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D)
6568 : (isArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D)));
6570 viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
6571 viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
6572 viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
6573 viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
6574 viewInfo.subresourceRange.aspectMask = aspectMask;
6580 viewInfo.subresourceRange.layerCount = isCube ? 6 : (isArray ?
qMax(0,
m_arraySize) : 1);
6583 VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo,
nullptr, &
imageView);
6584 if (err != VK_SUCCESS) {
6585 qWarning(
"Failed to create image view: %d", err);
6609 VkImageCreateInfo imageInfo = {};
6610 imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
6611 imageInfo.flags = 0;
6613 imageInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
6615 if (is3D && isRenderTarget) {
6621 if (!rhiD->caps.texture3DSliceAs2D)
6622 qWarning(
"QRhiVulkan: Rendering to 3D texture slice may not be functional without API 1.1 on the VkInstance");
6623#ifdef VK_VERSION_1_1
6624 imageInfo.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
6626 imageInfo.flags |= 0x00000020;
6630 imageInfo.imageType = is1D ? VK_IMAGE_TYPE_1D : is3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
6632 imageInfo.extent.width = uint32_t(
size.width());
6633 imageInfo.extent.height = uint32_t(
size.height());
6634 imageInfo.extent.depth = is3D ?
qMax(1,
m_depth) : 1;
6636 imageInfo.arrayLayers = isCube ? 6 : (isArray ?
qMax(0,
m_arraySize) : 1);
6638 imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
6639 imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
6641 imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
6642 if (isRenderTarget) {
6644 imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
6646 imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
6649 imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
6651 imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
6653 imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
6655 VmaAllocationCreateInfo allocInfo = {};
6656 allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
6660 if (err != VK_SUCCESS) {
6661 qWarning(
"Failed to create image (with VkImageCreateInfo %ux%u depth %u vkformat 0x%X mips %u layers %u vksamples 0x%X): %d",
6662 imageInfo.extent.width, imageInfo.extent.height, imageInfo.extent.depth,
6663 int(imageInfo.format),
6664 imageInfo.mipLevels,
6665 imageInfo.arrayLayers,
6666 int(imageInfo.samples),
6668 rhiD->printExtraErrorInfo(err);
6679 rhiD->registerResource(
this);
6685 VkImage
img = VkImage(
src.object);
6701 rhiD->registerResource(
this);
6727 VkImageViewCreateInfo viewInfo = {};
6728 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
6729 viewInfo.image =
image;
6730 viewInfo.viewType = isCube
6731 ? VK_IMAGE_VIEW_TYPE_CUBE
6732 : (is3D ? VK_IMAGE_VIEW_TYPE_3D
6733 : (is1D ? (isArray ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D)
6734 : (isArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D)));
6736 viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
6737 viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
6738 viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
6739 viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
6740 viewInfo.subresourceRange.aspectMask = aspectMask;
6741 viewInfo.subresourceRange.baseMipLevel = uint32_t(
level);
6742 viewInfo.subresourceRange.levelCount = 1;
6743 viewInfo.subresourceRange.baseArrayLayer = 0;
6744 viewInfo.subresourceRange.layerCount = isCube ? 6 : (isArray ?
qMax(0,
m_arraySize) : 1);
6746 VkImageView
v = VK_NULL_HANDLE;
6748 VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo,
nullptr, &
v);
6749 if (err != VK_SUCCESS) {
6750 qWarning(
"Failed to create image view: %d", err);
6751 return VK_NULL_HANDLE;
6760 :
QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u,
v,
w)
6783 rhiD->releaseQueue.append(e);
6784 rhiD->unregisterResource(
this);
6793 VkSamplerCreateInfo samplerInfo = {};
6794 samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
6801 samplerInfo.maxAnisotropy = 1.0f;
6807 VkResult err = rhiD->df->vkCreateSampler(rhiD->dev, &samplerInfo,
nullptr, &
sampler);
6808 if (err != VK_SUCCESS) {
6809 qWarning(
"Failed to create sampler: %d", err);
6815 rhiD->registerResource(
this);
6836 rp = VK_NULL_HANDLE;
6846 rp = VK_NULL_HANDLE;
6850 rhiD->releaseQueue.append(e);
6851 rhiD->unregisterResource(
this);
6857 return a.format ==
b.format
6858 &&
a.samples ==
b.samples
6859 &&
a.loadOp ==
b.loadOp
6860 &&
a.storeOp ==
b.storeOp
6861 &&
a.stencilLoadOp ==
b.stencilLoadOp
6862 &&
a.stencilStoreOp ==
b.stencilStoreOp
6863 &&
a.initialLayout ==
b.initialLayout
6864 &&
a.finalLayout ==
b.finalLayout;
6891 const uint32_t attIdx =
colorRefs[
i].attachment;
6892 if (attIdx !=
o->colorRefs[
i].attachment)
6899 const uint32_t attIdx =
dsRef.attachment;
6900 if (attIdx !=
o->dsRef.attachment)
6908 if (attIdx !=
o->resolveRefs[
i].attachment)
6916 if (attIdx !=
o->dsResolveRef.attachment)
6939 auto serializeAttachmentData = [
this, &
p](uint32_t attIdx) {
6940 const bool used = attIdx != VK_ATTACHMENT_UNUSED;
6941 const VkAttachmentDescription *
a = used ? &
attDescs[attIdx] :
nullptr;
6942 *
p++ = used ?
a->format : 0;
6943 *
p++ = used ?
a->samples : 0;
6944 *
p++ = used ?
a->loadOp : 0;
6945 *
p++ = used ?
a->storeOp : 0;
6946 *
p++ = used ?
a->stencilLoadOp : 0;
6947 *
p++ = used ?
a->stencilStoreOp : 0;
6948 *
p++ = used ?
a->initialLayout : 0;
6949 *
p++ = used ?
a->finalLayout : 0;
6953 const uint32_t attIdx =
colorRefs[
i].attachment;
6955 serializeAttachmentData(attIdx);
6959 const uint32_t attIdx =
dsRef.attachment;
6961 serializeAttachmentData(attIdx);
6967 serializeAttachmentData(attIdx);
6973 serializeAttachmentData(attIdx);
6992 VkRenderPassCreateInfo rpInfo;
6993 VkSubpassDescription subpassDesc;
6998 if (!multiViewHelper.prepare(&rpInfo,
multiViewCount, rhiD->caps.multiView)) {
7003 VkResult err = rhiD->df->vkCreateRenderPass(rhiD->dev, &rpInfo,
nullptr, &rpD->rp);
7004 if (err != VK_SUCCESS) {
7005 qWarning(
"Failed to create renderpass: %d", err);
7010 rpD->updateSerializedFormat();
7011 rhiD->registerResource(rpD);
7062 rtv[att] = VK_NULL_HANDLE;
7063 resrtv[att] = VK_NULL_HANDLE;
7082 d.
fb = VK_NULL_HANDLE;
7087 rtv[att] = VK_NULL_HANDLE;
7088 resrtv[att] = VK_NULL_HANDLE;
7092 dsv = VK_NULL_HANDLE;
7098 rhiD->releaseQueue.append(e);
7099 rhiD->unregisterResource(
this);
7109 if (!rhiD->createOffscreenRenderPass(rp,
7125 rhiD->registerResource(rp);
7139 QVarLengthArray<VkImageView, 8> views;
7152 const bool isMultiView =
it->multiViewCount() >= 2;
7155 VkImageViewCreateInfo viewInfo = {};
7156 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
7157 viewInfo.image = texD->image;
7158 viewInfo.viewType = is1D ? VK_IMAGE_VIEW_TYPE_1D
7159 : (isMultiView ? VK_IMAGE_VIEW_TYPE_2D_ARRAY
7160 : VK_IMAGE_VIEW_TYPE_2D);
7161 viewInfo.format = texD->viewFormat;
7162 viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
7163 viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
7164 viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
7165 viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
7166 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
7167 viewInfo.subresourceRange.baseMipLevel = uint32_t(
it->level());
7168 viewInfo.subresourceRange.levelCount = 1;
7169 viewInfo.subresourceRange.baseArrayLayer = uint32_t(
it->layer());
7170 viewInfo.subresourceRange.layerCount = uint32_t(isMultiView ?
it->multiViewCount() : 1);
7171 VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo,
nullptr, &
rtv[attIndex]);
7172 if (err != VK_SUCCESS) {
7173 qWarning(
"Failed to create render target image view: %d", err);
7176 views.append(
rtv[attIndex]);
7177 if (attIndex == 0) {
7178 d.
pixelSize = rhiD->q->sizeForMipLevel(
it->level(), texD->pixelSize());
7183 views.append(rbD->backingTexture->imageView);
7184 if (attIndex == 0) {
7192 if (hasDepthStencil) {
7196 VkImageViewCreateInfo viewInfo = {};
7197 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
7198 viewInfo.image = depthTexD->image;
7199 viewInfo.viewType =
d.
multiViewCount > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
7200 viewInfo.format = depthTexD->viewFormat;
7201 viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
7202 viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
7203 viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
7204 viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
7205 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
7206 viewInfo.subresourceRange.levelCount = 1;
7207 viewInfo.subresourceRange.layerCount = qMax<uint32_t>(1,
d.
multiViewCount);
7208 VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo,
nullptr, &
dsv);
7209 if (err != VK_SUCCESS) {
7210 qWarning(
"Failed to create depth-stencil image view for rt: %d", err);
7220 views.append(depthRbD->imageView);
7235 if (
it->resolveTexture()) {
7240 VkImageViewCreateInfo viewInfo = {};
7241 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
7242 viewInfo.image = resTexD->image;
7244 : VK_IMAGE_VIEW_TYPE_2D;
7245 viewInfo.format = resTexD->viewFormat;
7246 viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
7247 viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
7248 viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
7249 viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
7250 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
7251 viewInfo.subresourceRange.baseMipLevel = uint32_t(
it->resolveLevel());
7252 viewInfo.subresourceRange.levelCount = 1;
7253 viewInfo.subresourceRange.baseArrayLayer = uint32_t(
it->resolveLayer());
7254 viewInfo.subresourceRange.layerCount = qMax<uint32_t>(1,
d.
multiViewCount);
7255 VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo,
nullptr, &
resrtv[attIndex]);
7256 if (err != VK_SUCCESS) {
7257 qWarning(
"Failed to create render target resolve image view: %d", err);
7260 views.append(
resrtv[attIndex]);
7268 VkImageViewCreateInfo viewInfo = {};
7269 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
7270 viewInfo.image = resTexD->image;
7272 : VK_IMAGE_VIEW_TYPE_2D;
7273 viewInfo.format = resTexD->viewFormat;
7274 viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
7275 viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
7276 viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
7277 viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
7278 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
7279 viewInfo.subresourceRange.baseMipLevel = 0;
7280 viewInfo.subresourceRange.levelCount = 1;
7281 viewInfo.subresourceRange.baseArrayLayer = 0;
7282 viewInfo.subresourceRange.layerCount = qMax<uint32_t>(1,
d.
multiViewCount);
7283 VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo,
nullptr, &
resdsv);
7284 if (err != VK_SUCCESS) {
7285 qWarning(
"Failed to create render target depth resolve image view: %d", err);
7295 qWarning(
"QVkTextureRenderTarget: No renderpass descriptor set. See newCompatibleRenderPassDescriptor() and setRenderPassDescriptor().");
7300 VkFramebufferCreateInfo fbInfo = {};
7301 fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
7302 fbInfo.renderPass =
d.
rp->
rp;
7304 fbInfo.pAttachments = views.constData();
7309 VkResult err = rhiD->df->vkCreateFramebuffer(rhiD->dev, &fbInfo,
nullptr, &
d.
fb);
7310 if (err != VK_SUCCESS) {
7311 qWarning(
"Failed to create framebuffer: %d", err);
7318 rhiD->registerResource(
this);
7371 rhiD->releaseQueue.append(e);
7372 rhiD->unregisterResource(
this);
7382 if (!rhiD->sanityCheckShaderResourceBindings(
this))
7385 rhiD->updateLayoutDesc(
this);
7401 if (
b->u.ubuf.hasDynamicOffset)
7406 QVarLengthArray<VkDescriptorSetLayoutBinding, 4> vkbindings;
7409 VkDescriptorSetLayoutBinding vkbinding = {};
7410 vkbinding.binding = uint32_t(
b->binding);
7413 vkbinding.descriptorCount =
b->u.stex.count;
7415 vkbinding.descriptorCount = 1;
7417 vkbindings.append(vkbinding);
7420 VkDescriptorSetLayoutCreateInfo layoutInfo = {};
7421 layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
7422 layoutInfo.bindingCount = uint32_t(vkbindings.size());
7423 layoutInfo.pBindings = vkbindings.constData();
7425 VkResult err = rhiD->df->vkCreateDescriptorSetLayout(rhiD->dev, &layoutInfo,
nullptr, &
layout);
7426 if (err != VK_SUCCESS) {
7427 qWarning(
"Failed to create descriptor set layout: %d", err);
7431 VkDescriptorSetAllocateInfo allocInfo = {};
7432 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
7437 allocInfo.pSetLayouts = layouts;
7449 rhiD->registerResource(
this);
7505 rhiD->releaseQueue.append(e);
7506 rhiD->unregisterResource(
this);
7516 rhiD->pipelineCreationStart();
7517 if (!rhiD->sanityCheckGraphicsPipeline(
this))
7520 if (!rhiD->ensurePipelineCache())
7523 VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
7524 pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
7525 pipelineLayoutInfo.setLayoutCount = 1;
7528 pipelineLayoutInfo.pSetLayouts = &srbD->layout;
7529 VkResult err = rhiD->df->vkCreatePipelineLayout(rhiD->dev, &pipelineLayoutInfo,
nullptr, &
layout);
7530 if (err != VK_SUCCESS) {
7531 qWarning(
"Failed to create pipeline layout: %d", err);
7535 VkGraphicsPipelineCreateInfo pipelineInfo = {};
7536 pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
7538 QVarLengthArray<VkShaderModule, 4>
shaders;
7539 QVarLengthArray<VkPipelineShaderStageCreateInfo, 4> shaderStageCreateInfos;
7543 if (spirv.shader().isEmpty()) {
7544 qWarning() <<
"No SPIR-V 1.0 shader code found in baked shader" << bakedShader;
7547 VkShaderModule
shader = rhiD->createShader(spirv.shader());
7550 VkPipelineShaderStageCreateInfo shaderInfo = {};
7551 shaderInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
7553 shaderInfo.module =
shader;
7554 shaderInfo.pName = spirv.entryPoint().constData();
7555 shaderStageCreateInfos.append(shaderInfo);
7558 pipelineInfo.stageCount = uint32_t(shaderStageCreateInfos.size());
7559 pipelineInfo.pStages = shaderStageCreateInfos.constData();
7561 QVarLengthArray<VkVertexInputBindingDescription, 4> vertexBindings;
7562#ifdef VK_EXT_vertex_attribute_divisor
7563 QVarLengthArray<VkVertexInputBindingDivisorDescriptionEXT> nonOneStepRates;
7569 VkVertexInputBindingDescription bindingInfo = {
7573 ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE
7576#ifdef VK_EXT_vertex_attribute_divisor
7577 if (rhiD->caps.vertexAttribDivisor) {
7578 nonOneStepRates.append({ uint32_t(
bindingIndex),
it->instanceStepRate() });
7582 qWarning(
"QRhiVulkan: Instance step rates other than 1 not supported without "
7583 "VK_EXT_vertex_attribute_divisor on the device and "
7584 "VK_KHR_get_physical_device_properties2 on the instance");
7587 vertexBindings.append(bindingInfo);
7589 QVarLengthArray<VkVertexInputAttributeDescription, 4> vertexAttributes;
7593 VkVertexInputAttributeDescription attributeInfo = {
7594 uint32_t(
it->location()),
7595 uint32_t(
it->binding()),
7599 vertexAttributes.append(attributeInfo);
7601 VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
7602 vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
7603 vertexInputInfo.vertexBindingDescriptionCount = uint32_t(vertexBindings.size());
7604 vertexInputInfo.pVertexBindingDescriptions = vertexBindings.constData();
7605 vertexInputInfo.vertexAttributeDescriptionCount = uint32_t(vertexAttributes.size());
7606 vertexInputInfo.pVertexAttributeDescriptions = vertexAttributes.constData();
7607#ifdef VK_EXT_vertex_attribute_divisor
7608 VkPipelineVertexInputDivisorStateCreateInfoEXT divisorInfo = {};
7609 if (!nonOneStepRates.isEmpty()) {
7610 divisorInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
7611 divisorInfo.vertexBindingDivisorCount = uint32_t(nonOneStepRates.size());
7612 divisorInfo.pVertexBindingDivisors = nonOneStepRates.constData();
7613 vertexInputInfo.pNext = &divisorInfo;
7616 pipelineInfo.pVertexInputState = &vertexInputInfo;
7618 QVarLengthArray<VkDynamicState, 8> dynEnable;
7619 dynEnable << VK_DYNAMIC_STATE_VIEWPORT;
7620 dynEnable << VK_DYNAMIC_STATE_SCISSOR;
7622 dynEnable << VK_DYNAMIC_STATE_BLEND_CONSTANTS;
7624 dynEnable << VK_DYNAMIC_STATE_STENCIL_REFERENCE;
7626 VkPipelineDynamicStateCreateInfo dynamicInfo = {};
7627 dynamicInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
7628 dynamicInfo.dynamicStateCount = uint32_t(dynEnable.size());
7629 dynamicInfo.pDynamicStates = dynEnable.constData();
7630 pipelineInfo.pDynamicState = &dynamicInfo;
7632 VkPipelineViewportStateCreateInfo viewportInfo = {};
7633 viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
7634 viewportInfo.viewportCount = viewportInfo.scissorCount = 1;
7635 pipelineInfo.pViewportState = &viewportInfo;
7637 VkPipelineInputAssemblyStateCreateInfo inputAsmInfo = {};
7638 inputAsmInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
7641 pipelineInfo.pInputAssemblyState = &inputAsmInfo;
7643 VkPipelineTessellationStateCreateInfo tessInfo = {};
7644#ifdef VK_VERSION_1_1
7645 VkPipelineTessellationDomainOriginStateCreateInfo originInfo = {};
7648 tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
7656#ifdef VK_VERSION_1_1
7658 originInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
7659 originInfo.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
7660 tessInfo.pNext = &originInfo;
7662 qWarning(
"Proper tessellation support requires Vulkan 1.1 or newer, leaving domain origin unset");
7665 qWarning(
"QRhi was built without Vulkan 1.1 headers, this is not sufficient for proper tessellation support");
7668 pipelineInfo.pTessellationState = &tessInfo;
7671 VkPipelineRasterizationStateCreateInfo rastInfo = {};
7672 rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
7676 rastInfo.depthBiasEnable =
true;
7677 rastInfo.depthBiasConstantFactor = float(
m_depthBias);
7680 rastInfo.lineWidth = rhiD->caps.wideLines ?
m_lineWidth : 1.0f;
7682 pipelineInfo.pRasterizationState = &rastInfo;
7684 VkPipelineMultisampleStateCreateInfo msInfo = {};
7685 msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
7686 msInfo.rasterizationSamples = rhiD->effectiveSampleCountBits(
m_sampleCount);
7687 pipelineInfo.pMultisampleState = &msInfo;
7689 VkPipelineDepthStencilStateCreateInfo dsInfo = {};
7690 dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
7703 pipelineInfo.pDepthStencilState = &dsInfo;
7705 VkPipelineColorBlendStateCreateInfo blendInfo = {};
7706 blendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
7707 QVarLengthArray<VkPipelineColorBlendAttachmentState, 4> vktargetBlends;
7709 VkPipelineColorBlendAttachmentState blend = {};
7710 blend.blendEnable =
b.enable;
7718 vktargetBlends.append(blend);
7720 if (vktargetBlends.isEmpty()) {
7721 VkPipelineColorBlendAttachmentState blend = {};
7722 blend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
7723 | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
7724 vktargetBlends.append(blend);
7726 blendInfo.attachmentCount = uint32_t(vktargetBlends.size());
7727 blendInfo.pAttachments = vktargetBlends.constData();
7728 pipelineInfo.pColorBlendState = &blendInfo;
7730 pipelineInfo.layout =
layout;
7735 err = rhiD->df->vkCreateGraphicsPipelines(rhiD->dev, rhiD->pipelineCache, 1, &pipelineInfo,
nullptr, &
pipeline);
7738 rhiD->df->vkDestroyShaderModule(rhiD->dev,
shader,
nullptr);
7740 if (err != VK_SUCCESS) {
7741 qWarning(
"Failed to create graphics pipeline: %d", err);
7745 rhiD->pipelineCreationEnd();
7748 rhiD->registerResource(
this);
7779 rhiD->releaseQueue.append(e);
7780 rhiD->unregisterResource(
this);
7790 rhiD->pipelineCreationStart();
7791 if (!rhiD->ensurePipelineCache())
7794 VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
7795 pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
7796 pipelineLayoutInfo.setLayoutCount = 1;
7799 pipelineLayoutInfo.pSetLayouts = &srbD->layout;
7800 VkResult err = rhiD->df->vkCreatePipelineLayout(rhiD->dev, &pipelineLayoutInfo,
nullptr, &
layout);
7801 if (err != VK_SUCCESS) {
7802 qWarning(
"Failed to create pipeline layout: %d", err);
7806 VkComputePipelineCreateInfo pipelineInfo = {};
7807 pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
7808 pipelineInfo.layout =
layout;
7811 qWarning(
"Compute pipeline requires a compute shader stage");
7816 if (spirv.shader().isEmpty()) {
7817 qWarning() <<
"No SPIR-V 1.0 shader code found in baked shader" << bakedShader;
7821 qWarning() << bakedShader <<
"is not a compute shader";
7824 VkShaderModule
shader = rhiD->createShader(spirv.shader());
7825 VkPipelineShaderStageCreateInfo shaderInfo = {};
7826 shaderInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
7827 shaderInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
7828 shaderInfo.module =
shader;
7829 shaderInfo.pName = spirv.entryPoint().constData();
7830 pipelineInfo.stage = shaderInfo;
7832 err = rhiD->df->vkCreateComputePipelines(rhiD->dev, rhiD->pipelineCache, 1, &pipelineInfo,
nullptr, &
pipeline);
7833 rhiD->df->vkDestroyShaderModule(rhiD->dev,
shader,
nullptr);
7834 if (err != VK_SUCCESS) {
7835 qWarning(
"Failed to create graphics pipeline: %d", err);
7839 rhiD->pipelineCreationEnd();
7842 rhiD->registerResource(
this);
7884 rtWrapper(rhi,
this),
7885 rtWrapperRight(rhi,
this),
7897 if (
sc == VK_NULL_HANDLE)
7902 rhiD->swapchains.remove(
this);
7903 rhiD->releaseSwapChainResources(
this);
7908 frame.cmdBuf = VK_NULL_HANDLE;
7909 frame.timestampQueryIndex = -1;
7915 rhiD->unregisterResource(
this);
7940 VkSurfaceCapabilitiesKHR surfaceCaps = {};
7942 rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(rhiD->physDev,
surface, &surfaceCaps);
7943 VkExtent2D bufferSize = surfaceCaps.currentExtent;
7944 if (bufferSize.width == uint32_t(-1)) {
7945 Q_ASSERT(bufferSize.height == uint32_t(-1));
7948 return QSize(
int(bufferSize.width),
int(bufferSize.height));
7955 return s.format == VK_FORMAT_R16G16B16A16_SFLOAT
7956 &&
s.colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT;
7958 return (
s.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
s.format == VK_FORMAT_A2R10G10B10_UNORM_PACK32)
7959 &&
s.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT;
7961 return s.format == VK_FORMAT_R16G16B16A16_SFLOAT
7962 &&
s.colorSpace == VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT;
7975 qWarning(
"Attempted to call isFormatSupported() without a window set");
7980 VkSurfaceKHR surf = QVulkanInstance::surfaceForWindow(
m_window);
7983 uint32_t formatCount = 0;
7984 rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev, surf, &formatCount,
nullptr);
7985 QVarLengthArray<VkSurfaceFormatKHR, 8>
formats(formatCount);
7987 rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev, surf, &formatCount,
formats.data());
7988 for (uint32_t
i = 0;
i < formatCount; ++
i) {
8006 if (!rhiD->createDefaultRenderPass(rp,
8017 rhiD->registerResource(rp);
8024 case VK_FORMAT_R8_SRGB:
8025 case VK_FORMAT_R8G8_SRGB:
8026 case VK_FORMAT_R8G8B8_SRGB:
8027 case VK_FORMAT_B8G8R8_SRGB:
8028 case VK_FORMAT_R8G8B8A8_SRGB:
8029 case VK_FORMAT_B8G8R8A8_SRGB:
8030 case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
8045 VkSurfaceKHR surf = QVulkanInstance::surfaceForWindow(
m_window);
8047 qWarning(
"Failed to get surface for window");
8056 if (!rhiD->inst->supportsPresent(rhiD->physDev, rhiD->gfxQueueFamilyIdx,
m_window)) {
8057 qWarning(
"Presenting not supported on this window");
8062 rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev,
surface, &formatCount,
nullptr);
8063 QList<VkSurfaceFormatKHR>
formats(formatCount);
8065 rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev,
surface, &formatCount,
formats.data());
8069 const bool srgbRequested =
m_flags.testFlag(
sRGB);
8070 for (
int i = 0;
i < int(formatCount); ++
i) {
8086 rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR(rhiD->physDev,
surface, &presModeCount,
nullptr);
8088 rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR(rhiD->physDev,
surface, &presModeCount,
8111 if (!rhiD->recreateSwapChain(
this)) {
8112 qWarning(
"Failed to create new swapchain");
8116 if (needsRegistration)
8117 rhiD->swapchains.insert(
this);
8120 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
8127 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
8130 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
8137 qWarning(
"QVkSwapChain: No renderpass descriptor set. See newCompatibleRenderPassDescriptor() and setRenderPassDescriptor().");
8155 if (
samples > VK_SAMPLE_COUNT_1_BIT)
8162 VkImageView views[3] = {
8165 samples > VK_SAMPLE_COUNT_1_BIT ?
image.imageView : VK_NULL_HANDLE
8168 VkFramebufferCreateInfo fbInfo = {};
8169 fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
8172 fbInfo.pAttachments = views;
8177 VkResult err = rhiD->df->vkCreateFramebuffer(rhiD->dev, &fbInfo,
nullptr, &
image.fb);
8178 if (err != VK_SUCCESS) {
8179 qWarning(
"Failed to create framebuffer: %d", err);
8202 if (
samples > VK_SAMPLE_COUNT_1_BIT)
8209 VkImageView views[3] = {
8213 samples > VK_SAMPLE_COUNT_1_BIT ?
image.imageView : VK_NULL_HANDLE
8216 VkFramebufferCreateInfo fbInfo = {};
8217 fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
8221 fbInfo.pAttachments = views;
8226 VkResult err = rhiD->df->vkCreateFramebuffer(rhiD->dev, &fbInfo,
nullptr, &
image.fb);
8227 if (err != VK_SUCCESS) {
8228 qWarning(
"Failed to create framebuffer: %d", err);
8236 if (needsRegistration)
8237 rhiD->registerResource(
this);
IOBluetoothDevice * device
bool testBit(qsizetype i) const
Returns true if the bit at index position i is 1; otherwise returns false.
void setBit(qsizetype i)
Sets the bit at index position i to 1.
void clearBit(qsizetype i)
Sets the bit at index position i to 0.
qsizetype size() const
Returns the number of bits stored in the bit array.
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
The QColor class provides colors based on RGB, HSV or CMYK values.
qsizetype sizeInBytes() const
bool isNull() const
Returns true if it is a null image, otherwise returns false.
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
\inmodule QtCore\reentrant
constexpr bool isNull() const noexcept
Returns true if both the x and y coordinates are set to 0, otherwise returns false.
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr int y() const noexcept
Returns the y coordinate of this point.
const char * constData() const
Type
Specifies storage type of buffer resource.
QPair< int, quint32 > DynamicOffset
Synonym for QPair<int, quint32>.
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
IndexFormat
Specifies the index data type.
QRhiShaderStage m_shaderStage
QRhiShaderResourceBindings * m_shaderResourceBindings
QRhiRenderPassDescriptor * m_renderPassDesc
quint32 m_stencilReadMask
BlendOp
Specifies the blend operation.
PolygonMode
Specifies the polygon rasterization mode.
FrontFace
Specifies the front face winding order.
BlendFactor
Specifies the blend factor.
StencilOpState m_stencilFront
quint32 m_stencilWriteMask
CompareOp
Specifies the depth or stencil comparison function.
CullMode
Specifies the culling mode.
QVarLengthArray< QRhiShaderStage, 4 > m_shaderStages
QRhiVertexInputLayout m_vertexInputLayout
QVarLengthArray< TargetBlend, 8 > m_targetBlends
QRhiShaderResourceBindings * m_shaderResourceBindings
PolygonMode m_polygonMode
float m_slopeScaledDepthBias
Topology
Specifies the primitive topology.
StencilOpState m_stencilBack
StencilOp
Specifies the stencil operation.
int m_patchControlPointCount
int effectiveSampleCount(int sampleCount) const
bool isCompressedFormat(QRhiTexture::Format format) const
static const QRhiShaderResourceBinding::Data * shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
quint32 pipelineCacheRhiId() const
void compressedFormatInfo(QRhiTexture::Format format, const QSize &size, quint32 *bpl, quint32 *byteSize, QSize *blockDim) const
static bool sortedBindingLessThan(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
qint64 totalPipelineCreationTime() const
void textureFormatInfo(QRhiTexture::Format format, const QSize &size, quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
QRhiTexture * texture() const
void setPixelSize(const QSize &sz)
Sets the size (in pixels) to sz.
QRhiTexture::Format m_backingFormatHint
Type
Specifies the type of the renderbuffer.
virtual bool create()=0
Creates the corresponding native graphics resources.
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Sets the QRhiRenderPassDescriptor desc for use with this render target.
virtual QSize pixelSize() const =0
QRhiRenderPassDescriptor * m_renderPassDesc
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
virtual Type resourceType() const =0
void setName(const QByteArray &name)
Sets a name for the object.
QRhiImplementation * m_rhi
Filter
Specifies the minification, magnification, or mipmap filtering.
AddressMode
Specifies the addressing mode.
CompareOp
Specifies the texture comparison function.
std::array< int, 4 > scissor() const
Type
Specifies type of the shader resource bound to a binding point.
@ TessellationEvaluationStage
@ TessellationControlStage
QVarLengthArray< QRhiShaderResourceBinding, BINDING_PREALLOC > m_bindings
QShader::Variant shaderVariant() const
Type
Specifies the type of the shader stage.
@ SurfaceHasNonPreMulAlpha
QRhiRenderPassDescriptor * m_renderPassDesc
Format
Describes the swapchain format.
@ HDRExtendedDisplayP3Linear
StereoTargetBuffer
Selects the backbuffer to use with a stereoscopic swapchain.
QRhiRenderBuffer * m_depthStencil
QPoint destinationTopLeft() const
QPoint sourceTopLeft() const
int destinationLevel() const
int destinationLayer() const
const QRhiColorAttachment * cbeginColorAttachments() const
QRhiTexture * depthTexture() const
const QRhiColorAttachment * cendColorAttachments() const
QRhiRenderBuffer * depthStencilBuffer() const
qsizetype colorAttachmentCount() const
QRhiTexture * depthResolveTexture() const
QRhiTextureRenderTargetDescription m_desc
@ DoNotStoreDepthStencilContents
@ PreserveDepthStencilContents
quint32 dataStride() const
QPoint sourceTopLeft() const
QPoint destinationTopLeft() const
ViewFormat m_writeViewFormat
Format
Specifies the texture format.
ViewFormat m_readViewFormat
void setSampleCount(int s)
Sets the sample count to s.
void setPixelSize(const QSize &sz)
Sets the texture size, specified in pixels, to sz.
\variable QRhiVulkanInitParams::inst
QVarLengthArray< DescriptorPoolData, 8 > descriptorPools
void recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhiPassResourceTracker &tracker)
quint32 gfxQueueFamilyIdx
VkCommandBuffer startSecondaryCommandBuffer(QVkRenderTargetData *rtD=nullptr)
QRhiSwapChain * createSwapChain() override
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override
int resourceLimit(QRhi::ResourceLimit limit) const override
bool isDeviceLost() const override
void prepareUploadSubres(QVkTexture *texD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc, size_t *curOfs, void *mp, BufferImageCopyList *copyInfos)
VkPhysicalDeviceProperties physDevProperties
void executeDeferredReleases(bool forced=false)
uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex)
QRhi::FrameOpResult finish() override
quint32 timestampValidBits
QRhiTextureRenderTarget * createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override
bool createTransientImage(VkFormat format, const QSize &pixelSize, VkImageUsageFlags usage, VkImageAspectFlags aspectMask, VkSampleCountFlagBits samples, VkDeviceMemory *mem, VkImage *images, VkImageView *views, int count)
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override
void releaseCachedResources() override
QVkSwapChain * currentSwapChain
QByteArrayList requestedDeviceExtensions
bool createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasDepthStencil, VkSampleCountFlagBits samples, VkFormat colorFormat)
QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *importParams=nullptr)
void draw(QRhiCommandBuffer *cb, quint32 vertexCount, quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QList< int > supportedSampleCounts() const override
QRhiRenderBuffer * createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags, QRhiTexture::Format backingFormatHint) override
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override
QBitArray timestampQueryPoolMap
double elapsedSecondsFromTimestamp(quint64 timestamp[2], bool *ok)
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override
void trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, int slot, VkAccessFlags access, VkPipelineStageFlags stage)
void endExternal(QRhiCommandBuffer *cb) override
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override
VkPhysicalDeviceFeatures physDevFeatures
QRhiVulkanNativeHandles nativeHandlesStruct
bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex)
void updateShaderResourceBindings(QRhiShaderResourceBindings *srb, int descSetIdx=-1)
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override
VkResult createDescriptorPool(VkDescriptorPool *pool)
void prepareNewFrame(QRhiCommandBuffer *cb)
void subresourceBarrier(QVkCommandBuffer *cbD, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccess, VkAccessFlags dstAccess, VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage, int startLayer, int layerCount, int startLevel, int levelCount)
void printExtraErrorInfo(VkResult err)
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override
QRhi::FrameOpResult startPrimaryCommandBuffer(VkCommandBuffer *cb)
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override
void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker, QVkTexture *texD, QRhiPassResourceTracker::TextureAccess access, QRhiPassResourceTracker::TextureStage stage)
bool releaseCachedResourcesCalledBeforeFrameStart
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR
QRhiGraphicsPipeline * createGraphicsPipeline() override
QRhiComputePipeline * createComputePipeline() override
struct QRhiVulkan::@339 caps
QRhiTexture * createTexture(QRhiTexture::Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, QRhiTexture::Flags flags) override
void waitCommandCompletion(int frameSlot)
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR
bool recreateSwapChain(QRhiSwapChain *swapChain)
PFN_vkQueuePresentKHR vkQueuePresentKHR
bool ensurePipelineCache(const void *initialData=nullptr, size_t initialDataSize=0)
QRhiDriverInfo driverInfoStruct
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
QVarLengthArray< TextureReadback, 2 > activeTextureReadbacks
void depthStencilExplicitBarrier(QVkCommandBuffer *cbD, QVkRenderBuffer *rbD)
void trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD, VkImageLayout layout, VkAccessFlags access, VkPipelineStageFlags stage)
VkCommandPool cmdPool[QVK_FRAMES_IN_FLIGHT]
VkShaderModule createShader(const QByteArray &spirv)
void enqueueTransitionPassResources(QVkCommandBuffer *cbD)
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
bool create(QRhi::Flags flags) override
QVulkanDeviceFunctions * df
void setObjectName(uint64_t object, VkObjectType type, const QByteArray &name, int slot=-1)
bool isFeatureSupported(QRhi::Feature feature) const override
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR
QVarLengthArray< BufferReadback, 2 > activeBufferReadbacks
void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
bool isYUpInFramebuffer() const override
void debugMarkEnd(QRhiCommandBuffer *cb) override
QRhiSampler * createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) override
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR
void releaseSwapChainResources(QRhiSwapChain *swapChain)
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance) override
VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override
VkQueryPool timestampQueryPool
void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker, QVkBuffer *bufD, int slot, QRhiPassResourceTracker::BufferAccess access, QRhiPassResourceTracker::BufferStage stage)
VkFormat optimalDepthStencilFormat()
QRhiStats statistics() override
void setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps) override
void activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRenderTarget *rtD)
bool createOffscreenRenderPass(QVkRenderPassDescriptor *rpD, const QRhiColorAttachment *colorAttachmentsBegin, const QRhiColorAttachment *colorAttachmentsEnd, bool preserveColor, bool preserveDs, bool storeDs, QRhiRenderBuffer *depthStencilBuffer, QRhiTexture *depthTexture, QRhiTexture *depthResolveTexture)
PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR
void executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot)
bool isYUpInNDC() const override
const QRhiNativeHandles * nativeHandles() override
void setPipelineCacheData(const QByteArray &data) override
void setVertexInput(QRhiCommandBuffer *cb, int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat) override
QRhiShaderResourceBindings * createShaderResourceBindings() override
VkPipelineCache pipelineCache
void finishActiveReadbacks(bool forced=false)
void ensureCommandPoolForNewFrame()
QByteArray pipelineCacheData() override
QList< DeferredReleaseEntry > releaseQueue
void endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkCommandBuffer *cbD)
void beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, QRhiResourceUpdateBatch *resourceUpdates, QRhiCommandBuffer::BeginPassFlags flags) override
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override
QRhiBuffer * createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size) override
bool isClipDepthZeroToOne() const override
void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates)
QVarLengthArray< VkCommandBuffer, 4 > freeSecondaryCbs[QVK_FRAMES_IN_FLIGHT]
void setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int dynamicOffsetCount, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override
PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR
QMatrix4x4 clipSpaceCorrMatrix() const override
struct QRhiVulkan::OffscreenFrame ofr
QSet< QVkSwapChain * > swapchains
int ubufAlignment() const override
QRhiDriverInfo driverInfo() const override
void beginExternal(QRhiCommandBuffer *cb) override
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override
QRhi::FrameOpResult endAndSubmitPrimaryCommandBuffer(VkCommandBuffer cb, VkFence cmdFence, VkSemaphore *waitSem, VkSemaphore *signalSem)
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override
VkSampleCountFlagBits effectiveSampleCountBits(int sampleCount)
bool makeThreadLocalNativeContextCurrent() override
static constexpr int MAX_MIP_LEVELS
ResourceLimit
Describes the resource limit to query.
@ MaxThreadsPerThreadGroup
@ MaxThreadGroupsPerDimension
Feature
Flag values to indicate what features are supported by the backend currently in use.
@ NonDynamicUniformBuffers
@ RenderToNonBaseMipLevel
@ MultisampleRenderBuffer
@ PipelineCacheDataLoadSave
@ ReadBackNonUniformBuffer
@ RenderToOneDimensionalTexture
@ OneDimensionalTextureMipmaps
@ ReadBackNonBaseMipLevel
@ ThreeDimensionalTextureMipmaps
@ NonFourAlignedEffectiveIndexBufferOffset
@ ThreeDimensionalTextures
@ ReadBackAnyTextureFormat
FrameOpResult
Describes the result of operations that can have a soft failure.
@ FrameOpSwapChainOutOfDate
@ EnablePipelineCacheDataSave
QByteArray shader() const
QShaderCode shader(const QShaderKey &key) const
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
constexpr size_type size() const noexcept
void resize(qsizetype sz)
const_iterator cbegin() const noexcept
const_iterator cend() const noexcept
iterator begin() noexcept
The QVulkanDeviceFunctions class provides cross-platform access to the device level core Vulkan 1....
The QVulkanInstance class represents a native Vulkan instance, enabling Vulkan rendering onto a QSurf...
QSize size() const override
Returns the size of the window excluding any window frame.
static VulkanServerBufferGlFunctions * funcs
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define Q_STATIC_ASSERT(Condition)
#define QByteArrayLiteral(str)
#define QT_WARNING_DISABLE_GCC(text)
#define QT_WARNING_DISABLE_CLANG(text)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
static QString header(const QString &name)
static const qint64 headerSize
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
bool qFuzzyIsNull(qfloat16 f) noexcept
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLuint const GLuint * buffers
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLsizei const GLchar * label
[43]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLuint GLsizei const GLenum * props
GLenum GLuint GLintptr offset
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint GLsizei GLsizei GLenum format
GLsizei GLenum GLsizei GLsizei GLuint memory
GLfloat GLfloat GLfloat GLfloat h
GLuint GLsizei const GLuint const GLintptr * offsets
GLdouble GLdouble GLdouble GLdouble q
GLsizei GLsizei GLuint * shaders
GLint GLfloat GLint stencil
GLenum GLenum colorFormat
GLsizeiptr const void GLenum usage
Int aligned(Int v, Int byteAlign)
static bool isDepthTextureFormat(QRhiTexture::Format format)
static QRhiTexture::Format swapchainReadbackTextureFormat(DXGI_FORMAT format, QRhiTexture::Flags *flags)
static QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const QGles2Buffer::UsageState &bufUsage)
static VkPolygonMode toVkPolygonMode(QRhiGraphicsPipeline::PolygonMode mode)
static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wrap_vkGetInstanceProcAddr(VkInstance, const char *pName)
static VkCullModeFlags toVkCullMode(QRhiGraphicsPipeline::CullMode c)
static bool accessIsWrite(VkAccessFlags access)
static VkCompareOp toVkTextureCompareOp(QRhiSampler::CompareOp op)
static VkBufferUsageFlagBits toVkBufferUsage(QRhiBuffer::UsageFlags usage)
static QRhiTexture::Format swapchainReadbackTextureFormat(VkFormat format, QRhiTexture::Flags *flags)
static VkStencilOp toVkStencilOp(QRhiGraphicsPipeline::StencilOp op)
static bool qvk_debug_filter(QVulkanInstance::DebugMessageSeverityFlags severity, QVulkanInstance::DebugMessageTypeFlags type, const void *callbackData)
static struct @370 qvk_sampleCounts[]
static QVkBuffer::UsageState toVkBufferUsageState(QRhiPassResourceTracker::UsageState usage)
static bool attachmentDescriptionEquals(const VkAttachmentDescription &a, const VkAttachmentDescription &b)
static bool isSrgbFormat(VkFormat format)
static VkAccessFlags toVkAccess(QRhiPassResourceTracker::BufferAccess access)
static VkImageLayout toVkLayout(QRhiPassResourceTracker::TextureAccess access)
static VkFormat toVkAttributeFormat(QRhiVertexInputAttribute::Format format)
static QVkTexture::UsageState toVkTextureUsageState(QRhiPassResourceTracker::UsageState usage)
static VkPipelineStageFlags toVkPipelineStage(QRhiPassResourceTracker::BufferStage stage)
Int aligned(Int v, Int byteAlign)
\variable QRhiVulkanRenderPassNativeHandles::renderPass
static QRhiDriverInfo::DeviceType toRhiDeviceType(VkPhysicalDeviceType type)
static QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const QVkBuffer::UsageState &bufUsage)
static VkColorComponentFlags toVkColorComponents(QRhiGraphicsPipeline::ColorMask c)
static VkFilter toVkFilter(QRhiSampler::Filter f)
static VkPrimitiveTopology toVkTopology(QRhiGraphicsPipeline::Topology t)
static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wrap_vkGetDeviceProcAddr(VkDevice device, const char *pName)
static void qrhivk_releaseTexture(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df, void *allocator)
static void qrhivk_releaseBuffer(const QRhiVulkan::DeferredReleaseEntry &e, void *allocator)
static VmaAllocator toVmaAllocator(QVkAllocator a)
static QVulkanInstance * globalVulkanInstance
static VkSamplerAddressMode toVkAddressMode(QRhiSampler::AddressMode m)
static constexpr bool isDepthTextureFormat(QRhiTexture::Format format)
static void fillVkStencilOpState(VkStencilOpState *dst, const QRhiGraphicsPipeline::StencilOpState &src)
static VkShaderStageFlags toVkShaderStageFlags(QRhiShaderResourceBinding::StageFlags stage)
static constexpr VkImageAspectFlags aspectMaskForTextureFormat(QRhiTexture::Format format)
static VkDescriptorType toVkDescriptorType(const QRhiShaderResourceBinding::Data *b)
static VkBlendFactor toVkBlendFactor(QRhiGraphicsPipeline::BlendFactor f)
static VkBlendOp toVkBlendOp(QRhiGraphicsPipeline::BlendOp op)
static void qrhivk_releaseRenderBuffer(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df)
static VkFrontFace toVkFrontFace(QRhiGraphicsPipeline::FrontFace f)
void qrhivk_accumulateComputeResource(T *writtenResources, QRhiResource *resource, QRhiShaderResourceBinding::Type bindingType, int loadTypeVal, int storeTypeVal, int loadStoreTypeVal)
static VkFormat toVkTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
static VkCompareOp toVkCompareOp(QRhiGraphicsPipeline::CompareOp op)
static void fillRenderPassCreateInfo(VkRenderPassCreateInfo *rpInfo, VkSubpassDescription *subpassDesc, QVkRenderPassDescriptor *rpD)
static VkSamplerMipmapMode toVkMipmapMode(QRhiSampler::Filter f)
static bool hdrFormatMatchesVkSurfaceFormat(QRhiSwapChain::Format f, const VkSurfaceFormatKHR &s)
static void qrhivk_releaseSampler(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df)
static QVkRenderTargetData * maybeRenderTargetData(QVkCommandBuffer *cbD)
static VmaAllocation toVmaAllocation(QVkAlloc a)
static VkShaderStageFlagBits toVkShaderStage(QRhiShaderStage::Type type)
static const int QVK_UNIFORM_BUFFERS_PER_POOL
static const int QVK_COMBINED_IMAGE_SAMPLERS_PER_POOL
static const int QVK_STORAGE_BUFFERS_PER_POOL
static const int QVK_STORAGE_IMAGES_PER_POOL
static const int QVK_MAX_ACTIVE_TIMESTAMP_PAIRS
static const int QVK_DESC_SETS_PER_POOL
static const int QVK_FRAMES_IN_FLIGHT
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
std::unique_ptr< ThunkPool::ThunkAllocation > allocation
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
unsigned long long quint64
QList< QImage > images
[6]
view viewport() -> scroll(dx, dy, deviceRect)
bool prepare(VkRenderPassCreateInfo *rpInfo, int multiViewCount, bool multiViewCap)
DeviceType
Specifies the graphics device's type, when the information is available.
\variable QRhiGraphicsPipeline::TargetBlend::colorWrite
\variable QRhiReadbackResult::completed
std::function< void()> completed
QRhiReadbackResult * result
QRhiTextureCopyDescription desc
QRhiReadbackDescription rb
QVarLengthArray< MipLevelUploadList, 6 > subresDesc
QRhiReadbackResult * result
qint64 totalPipelineCreationTime
QRhiTexture::Format format
struct QRhiVulkan::DeferredReleaseEntry::@340::@349 renderPass
struct QRhiVulkan::DeferredReleaseEntry::@340::@343 shaderResourceBindings
struct QRhiVulkan::DeferredReleaseEntry::@340::@342 pipelineState
struct QRhiVulkan::DeferredReleaseEntry::@340::@351 secondaryCommandBuffer
struct QRhiVulkan::DeferredReleaseEntry::@340::@346 texture
struct QRhiVulkan::DeferredReleaseEntry::@340::@344 buffer
struct QRhiVulkan::DeferredReleaseEntry::@340::@348 textureRenderTarget
struct QRhiVulkan::DeferredReleaseEntry::@340::@345 renderBuffer
VkPipelineStageFlags stage
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
UsageState usageState[QVK_FRAMES_IN_FLIGHT]
VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT]
QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT]
QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT]
void endFullDynamicBufferUpdateForCurrentFrame() override
To be called when the entire contents of the buffer data has been updated in the memory block returne...
QRhiBuffer::NativeBuffer nativeBuffer() override
bool create() override
Creates the corresponding native graphics resources.
QVarLengthArray< DynamicUpdate, 16 > pendingDynamicUpdates[QVK_FRAMES_IN_FLIGHT]
char * beginFullDynamicBufferUpdateForCurrentFrame() override
union QVkCommandBuffer::Command::Args args
@ TransitionPassResources
struct QVkCommandBuffer::@313 pools
VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT]
QVkCommandBuffer(QRhiImplementation *rhi)
QVarLengthArray< VkCommandBuffer, 4 > activeSecondaryCbStack
QRhiBackendCommandList< Command > commands
QRhiRenderTarget * currentTarget
QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct
quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT]
QRhiComputePipeline * currentComputePipeline
const QRhiNativeHandles * nativeHandles()
QRhiShaderResourceBindings * currentComputeSrb
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiShaderResourceBindings * currentGraphicsSrb
VkBuffer currentIndexBuffer
uint currentSrbGeneration
QRhiGraphicsPipeline * currentGraphicsPipeline
int currentPassResTrackerIndex
uint currentPipelineGeneration
quint32 currentIndexOffset
QVarLengthArray< QRhiPassResourceTracker, 8 > passResTrackers
struct QVkCommandBuffer::@312 computePassState
VkIndexType currentIndexFormat
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QVkComputePipeline(QRhiImplementation *rhi)
QVkGraphicsPipeline(QRhiImplementation *rhi)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, int sampleCount, Flags flags, QRhiTexture::Format backingFormatHint)
QRhiTexture::Format backingFormat() const override
bool create() override
Creates the corresponding native graphics resources.
QVkTexture * backingTexture
QVarLengthArray< VkSubpassDependency, 2 > subpassDeps
const QRhiNativeHandles * nativeHandles() override
void updateSerializedFormat()
QVector< quint32 > serializedFormatData
bool hasDepthStencilResolve
QVarLengthArray< VkAttachmentReference, 8 > colorRefs
~QVkRenderPassDescriptor()
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() const override
VkAttachmentReference dsRef
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QVarLengthArray< VkAttachmentReference, 8 > resolveRefs
QVarLengthArray< VkAttachmentDescription, 8 > attDescs
QRhiVulkanRenderPassNativeHandles nativeHandlesStruct
VkAttachmentReference dsResolveRef
QVector< quint32 > serializedFormat() const override
QVkRenderPassDescriptor(QRhiImplementation *rhi)
bool isCompatible(const QRhiRenderPassDescriptor *other) const override
QVkRenderPassDescriptor * rp
QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList
static const int MAX_COLOR_ATTACHMENTS
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, AddressMode u, AddressMode v, AddressMode w)
VkDescriptorSetLayout layout
void updateResources(UpdateFlags flags) override
QVkShaderResourceBindings(QRhiImplementation *rhi)
QVarLengthArray< QRhiShaderResourceBinding, 8 > sortedBindings
QVarLengthArray< BoundResourceData, 8 > boundResourceData[QVK_FRAMES_IN_FLIGHT]
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
VkDescriptorSet descSets[QVK_FRAMES_IN_FLIGHT]
~QVkShaderResourceBindings()
QSize pixelSize() const override
int sampleCount() const override
float devicePixelRatio() const override
~QVkSwapChainRenderTarget()
QVkSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
@ ScImageUseTransferSource
VkColorSpaceKHR colorSpace
VkSurfaceKHR lastConnectedSurface
bool createOrResize() override
Creates the swapchain if not already done and resizes the swapchain buffers to match the current size...
bool isFormatSupported(Format f) override
QVkCommandBuffer cbWrapper
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
VkSampleCountFlagBits samples
struct QVkSwapChain::FrameResources frameRes[QVK_FRAMES_IN_FLIGHT]
QVkSwapChain(QRhiImplementation *rhi)
QSize surfacePixelSize() override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiRenderTarget * currentFrameRenderTarget() override
quint32 currentImageIndex
QVarLengthArray< ImageResources, EXPECTED_MAX_BUFFER_COUNT > imageRes
QVarLengthArray< VkPresentModeKHR, 8 > supportedPresentationModes
QVkSwapChainRenderTarget rtWrapperRight
QVkSwapChainRenderTarget rtWrapper
QRhiCommandBuffer * currentFrameCommandBuffer() override
QVkTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags)
~QVkTextureRenderTarget()
float devicePixelRatio() const override
VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS]
bool create() override
Creates the corresponding native graphics resources.
int sampleCount() const override
QSize pixelSize() const override
VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS]
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
VkPipelineStageFlags stage
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT]
VkImageView perLevelImageViewForLoadStore(int level)
VkSampleCountFlagBits samples
QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT]
bool createFrom(NativeTexture src) override
Similar to create(), except that no new native textures are created.
void setNativeLayout(int layout) override
With some graphics APIs, such as Vulkan, integrating custom rendering code that uses the graphics API...
VkFormat viewFormatForSampling
QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, Flags flags)
VkImageView perLevelImageViews[QRhi::MAX_MIP_LEVELS]
NativeTexture nativeTexture() override
bool prepareCreate(QSize *adjustedSize=nullptr)