VkFormat VkHelper::findSupportedFormat(VkPhysicalDevice physicalDevice, const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { for (auto format : candidates) { VkFormatProperties props; vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props); if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) return format; else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) return format; } throw std::runtime_error("ERROR: Failed to find supported format."); return VkFormat(); }
bool WrappedVulkan::Serialise_vkCreateDevice( Serialiser* localSerialiser, VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) { SERIALISE_ELEMENT(ResourceId, physId, GetResID(physicalDevice)); SERIALISE_ELEMENT(VkDeviceCreateInfo, serCreateInfo, *pCreateInfo); SERIALISE_ELEMENT(ResourceId, devId, GetResID(*pDevice)); if(m_State == READING) { // we must make any modifications locally, so the free of pointers // in the serialised VkDeviceCreateInfo don't double-free VkDeviceCreateInfo createInfo = serCreateInfo; std::vector<string> Extensions; for(uint32_t i=0; i < createInfo.enabledExtensionCount; i++) { // don't include the debug marker extension if(strcmp(createInfo.ppEnabledExtensionNames[i], VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) Extensions.push_back(createInfo.ppEnabledExtensionNames[i]); } std::vector<string> Layers; for(uint32_t i=0; i < createInfo.enabledLayerCount; i++) Layers.push_back(createInfo.ppEnabledLayerNames[i]); StripUnwantedLayers(Layers); AddRequiredExtensions(false, Extensions); #if defined(FORCE_VALIDATION_LAYERS) Layers.push_back("VK_LAYER_LUNARG_standard_validation"); #endif createInfo.enabledLayerCount = (uint32_t)Layers.size(); const char **layerArray = NULL; if(!Layers.empty()) { layerArray = new const char *[createInfo.enabledLayerCount]; for(uint32_t i=0; i < createInfo.enabledLayerCount; i++) layerArray[i] = Layers[i].c_str(); createInfo.ppEnabledLayerNames = layerArray; } createInfo.enabledExtensionCount = (uint32_t)Extensions.size(); const char **extArray = NULL; if(!Extensions.empty()) { extArray = new const char *[createInfo.enabledExtensionCount]; for(uint32_t i=0; i < createInfo.enabledExtensionCount; i++) extArray[i] = Extensions[i].c_str(); createInfo.ppEnabledExtensionNames = extArray; } physicalDevice = GetResourceManager()->GetLiveHandle<VkPhysicalDevice>(physId); VkDevice device; uint32_t qCount = 0; ObjDisp(physicalDevice)->GetPhysicalDeviceQueueFamilyProperties(Unwrap(physicalDevice), &qCount, NULL); VkQueueFamilyProperties *props = new VkQueueFamilyProperties[qCount]; ObjDisp(physicalDevice)->GetPhysicalDeviceQueueFamilyProperties(Unwrap(physicalDevice), &qCount, props); bool found = false; uint32_t qFamilyIdx = 0; VkQueueFlags search = (VK_QUEUE_GRAPHICS_BIT); // for queue priorities, if we need it float one = 1.0f; // if we need to change the requested queues, it will point to this VkDeviceQueueCreateInfo *modQueues = NULL; for(uint32_t i=0; i < createInfo.queueCreateInfoCount; i++) { uint32_t idx = createInfo.pQueueCreateInfos[i].queueFamilyIndex; RDCASSERT(idx < qCount); // this requested queue is one we can use too if((props[idx].queueFlags & search) == search && createInfo.pQueueCreateInfos[i].queueCount > 0) { qFamilyIdx = idx; found = true; break; } } // if we didn't find it, search for which queue family we should add a request for if(!found) { RDCDEBUG("App didn't request a queue family we can use - adding our own"); for(uint32_t i=0; i < qCount; i++) { if((props[i].queueFlags & search) == search) { qFamilyIdx = i; found = true; break; } } if(!found) { SAFE_DELETE_ARRAY(props); RDCERR("Can't add a queue with required properties for RenderDoc! Unsupported configuration"); } else { // we found the queue family, add it modQueues = new VkDeviceQueueCreateInfo[createInfo.queueCreateInfoCount + 1]; for(uint32_t i=0; i < createInfo.queueCreateInfoCount; i++) modQueues[i] = createInfo.pQueueCreateInfos[i]; modQueues[createInfo.queueCreateInfoCount].queueFamilyIndex = qFamilyIdx; modQueues[createInfo.queueCreateInfoCount].queueCount = 1; modQueues[createInfo.queueCreateInfoCount].pQueuePriorities = &one; createInfo.pQueueCreateInfos = modQueues; createInfo.queueCreateInfoCount++; } } SAFE_DELETE_ARRAY(props); VkPhysicalDeviceFeatures enabledFeatures = {0}; if(createInfo.pEnabledFeatures != NULL) enabledFeatures = *createInfo.pEnabledFeatures; createInfo.pEnabledFeatures = &enabledFeatures; VkPhysicalDeviceFeatures availFeatures = {0}; ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &availFeatures); if(availFeatures.fillModeNonSolid) enabledFeatures.fillModeNonSolid = true; else RDCWARN("fillModeNonSolid = false, wireframe overlay will be solid"); if(availFeatures.robustBufferAccess) enabledFeatures.robustBufferAccess = true; else RDCWARN("robustBufferAccess = false, out of bounds access due to bugs in application or RenderDoc may cause crashes"); if(availFeatures.vertexPipelineStoresAndAtomics) enabledFeatures.vertexPipelineStoresAndAtomics = true; else RDCWARN("vertexPipelineStoresAndAtomics = false, output mesh data will not be available"); uint32_t numExts = 0; VkResult vkr = ObjDisp(physicalDevice)->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &numExts, NULL); RDCASSERTEQUAL(vkr, VK_SUCCESS); VkExtensionProperties *exts = new VkExtensionProperties[numExts]; vkr = ObjDisp(physicalDevice)->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &numExts, exts); RDCASSERTEQUAL(vkr, VK_SUCCESS); for(uint32_t i=0; i < numExts; i++) RDCLOG("Ext %u: %s (%u)", i, exts[i].extensionName, exts[i].specVersion); SAFE_DELETE_ARRAY(exts); // PORTABILITY check that extensions and layers supported in capture (from createInfo) are supported in replay vkr = GetDeviceDispatchTable(NULL)->CreateDevice(Unwrap(physicalDevice), &createInfo, NULL, &device); RDCASSERTEQUAL(vkr, VK_SUCCESS); GetResourceManager()->WrapResource(device, device); GetResourceManager()->AddLiveResource(devId, device); InitDeviceReplayTables(Unwrap(device)); RDCASSERT(m_Device == VK_NULL_HANDLE); // MULTIDEVICE m_PhysicalDevice = physicalDevice; m_Device = device; m_QueueFamilyIdx = qFamilyIdx; if(m_InternalCmds.cmdpool == VK_NULL_HANDLE) { VkCommandPoolCreateInfo poolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, NULL, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, qFamilyIdx }; vkr = ObjDisp(device)->CreateCommandPool(Unwrap(device), &poolInfo, NULL, &m_InternalCmds.cmdpool); RDCASSERTEQUAL(vkr, VK_SUCCESS); GetResourceManager()->WrapResource(Unwrap(device), m_InternalCmds.cmdpool); } ObjDisp(physicalDevice)->GetPhysicalDeviceProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.props); ObjDisp(physicalDevice)->GetPhysicalDeviceMemoryProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.memProps); ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &m_PhysicalDeviceData.features); for(int i=VK_FORMAT_BEGIN_RANGE+1; i < VK_FORMAT_END_RANGE; i++) ObjDisp(physicalDevice)->GetPhysicalDeviceFormatProperties(Unwrap(physicalDevice), VkFormat(i), &m_PhysicalDeviceData.fmtprops[i]); m_PhysicalDeviceData.readbackMemIndex = m_PhysicalDeviceData.GetMemoryIndex(~0U, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0); m_PhysicalDeviceData.uploadMemIndex = m_PhysicalDeviceData.GetMemoryIndex(~0U, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0); m_PhysicalDeviceData.GPULocalMemIndex = m_PhysicalDeviceData.GetMemoryIndex(~0U, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); for(size_t i=0; i < m_PhysicalDevices.size(); i++) { if(physicalDevice == m_PhysicalDevices[i]) { m_PhysicalDeviceData.memIdxMap = m_MemIdxMaps[i]; break; } } m_DebugManager = new VulkanDebugManager(this, device); SAFE_DELETE_ARRAY(modQueues); SAFE_DELETE_ARRAY(layerArray); SAFE_DELETE_ARRAY(extArray); } return true; }