这是主要的呼叫者功能
void createVulkanContext()
{
queueFamilyCount = 0;
populatePhysicalDevice(&instance, &physicalDevice);
physicalDeviceTest(&physicalDevice); // This one works fine
populateQueueFamilies(physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, surface);
physicalDeviceTest(&physicalDevice); // This one causes segfault
}
这是查询功能
void physicalDeviceTest(VkPhysicalDevice* gPhysicalDevice)
{
printf("%p\n", gPhysicalDevice);
VkPhysicalDeviceProperties pdProp;
vkGetPhysicalDeviceProperties(*gPhysicalDevice, &pdProp);
printf("%u\n", pdProp.deviceID);
printf("%s\n", pdProp.deviceName);
printf("%u\n", pdProp.apiVersion);
printf("%u\n", pdProp.driverVersion);
printf("%u\n", pdProp.vendorID);
}
哪个打印
0x55555555a1e8
26958
Unknown AMD GPU
4198513
8388708
4098
0x55555555a1e8
这是
gdb backtrace
结果Thread 1 "VulkanApp1090" received signal SIGSEGV, Segmentation fault.
0x00007ffff7f63467 in vkGetPhysicalDeviceProperties () from /usr/lib/libvulkan.so.1
(gdb) backtrace
#0 0x00007ffff7f63467 in vkGetPhysicalDeviceProperties () from /usr/lib/libvulkan.so.1
#1 0x0000555555555602 in physicalDeviceTest (gPhysicalDevice=0x55555555a1e8 <physicalDevice>)
据我所知,这应该不会发生,因为
populateQueueFamilies(physicalDevice, &queueFamilyIndicesList ...)
函数并没有真正改变按值传递的physicalDevice
变量。完整代码
typedef struct QueueFamilyIndices
{
int graphicsFamilySupportQueueIndex;
int computeFamilySupportQueueIndex;
int transferFamilySupportQueueIndex;
int sparsebindingFamilySupportQueueIndex;
int protectedFamilySupportQueueIndex;
int presentFamilySupportQueueIndex;
} QueueFamilyIndices;
VkInstance instance;
VkPhysicalDevice physicalDevice;
VkDevice logicalDevice;
QueueFamilyIndices* queueFamilyIndicesList;
QueueFamilyIndices selectedQueueFamilyIndex;
uint32_t queueFamilyCount;
VkQueue graphicsQueue;
VkSurfaceKHR surface;
void populateQueueFamilyQueueIndices(VkQueueFamilyProperties gQueueFamilyProperties,
uint32_t gQueueFamilyIndex,
QueueFamilyIndices* gQueueFamilyIndices)
{
gQueueFamilyIndices->graphicsFamilySupportQueueIndex = -1;
gQueueFamilyIndices->computeFamilySupportQueueIndex = -1;
gQueueFamilyIndices->transferFamilySupportQueueIndex = -1;
gQueueFamilyIndices->sparsebindingFamilySupportQueueIndex = -1;
gQueueFamilyIndices->protectedFamilySupportQueueIndex = -1;
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
gQueueFamilyIndices->graphicsFamilySupportQueueIndex = gQueueFamilyIndex;
}
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_COMPUTE_BIT)
{
gQueueFamilyIndices->computeFamilySupportQueueIndex = gQueueFamilyIndex;
}
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_TRANSFER_BIT)
{
gQueueFamilyIndices->transferFamilySupportQueueIndex = gQueueFamilyIndex;
}
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT)
{
gQueueFamilyIndices->sparsebindingFamilySupportQueueIndex = gQueueFamilyIndex;
}
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_PROTECTED_BIT)
{
gQueueFamilyIndices->protectedFamilySupportQueueIndex = gQueueFamilyIndex;
}
}
void populateQueueFamilies(VkPhysicalDevice gPhysicalDevice,
QueueFamilyIndices** gQueueFamilyIndicesList,
uint32_t* gQueueFamilyCount,
VkSurfaceKHR surface)
{
uint32_t queueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(gPhysicalDevice, &queueFamilyCount, VK_NULL_HANDLE);
VkQueueFamilyProperties queueFamilies[queueFamilyCount];
vkGetPhysicalDeviceQueueFamilyProperties(gPhysicalDevice, &queueFamilyCount, queueFamilies);
VkBool32 presentFamilySupported;
*gQueueFamilyIndicesList = malloc(sizeof(QueueFamilyIndices*) * queueFamilyCount);
for (uint32_t i = 0; i < queueFamilyCount; ++i)
{
QueueFamilyIndices gQueueFamilyIndices;
populateQueueFamilyQueueIndices(queueFamilies[i], i, &gQueueFamilyIndices);
presentFamilySupported = false;
vkGetPhysicalDeviceSurfaceSupportKHR(gPhysicalDevice, i, surface, &presentFamilySupported);
gQueueFamilyIndices.presentFamilySupportQueueIndex = presentFamilySupported ? i : -1;
gQueueFamilyIndicesList[i] = malloc(sizeof(QueueFamilyIndices));
*gQueueFamilyIndicesList[i] = gQueueFamilyIndices;
}
*gQueueFamilyCount = queueFamilyCount;
}
void physicalDeviceTest(VkPhysicalDevice* gPhysicalDevice)
{
printf("%p\n", gPhysicalDevice);
VkPhysicalDeviceProperties pdProp;
vkGetPhysicalDeviceProperties(*gPhysicalDevice, &pdProp);
printf("%u\n", pdProp.deviceID);
printf("%s\n", pdProp.deviceName);
printf("%u\n", pdProp.apiVersion);
printf("%u\n", pdProp.driverVersion);
printf("%u\n", pdProp.vendorID);
}
void createVulkanContext()
{
queueFamilyCount = 0;
populatePhysicalDevice(&instance, &physicalDevice);
physicalDeviceTest(&physicalDevice); // This one works fine
populateQueueFamilies(physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, surface);
physicalDeviceTest(&physicalDevice); // This one causes segfault
}
诊断更多让我思考
gQueueFamilyIndicesList[i] = malloc(sizeof(QueueFamilyIndices));
*gQueueFamilyIndicesList[i] = gQueueFamilyIndices;
因为将它们注释掉可以修复段错误。
TL; DR
再次调用相同的函数(
physicalDeviceTest
)会导致段错误void createVulkanContext()
{
queueFamilyCount = 0;
populatePhysicalDevice(&instance, &physicalDevice);
physicalDeviceTest(&physicalDevice); // This one works fine
populateQueueFamilies(physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, surface);
physicalDeviceTest(&physicalDevice); // This one causes segfault
}
可能是由于这些电话
gQueueFamilyIndicesList[i] = malloc(sizeof(QueueFamilyIndices));
*gQueueFamilyIndicesList[i] = gQueueFamilyIndices;
在函数
populateQueueFamilies
中,尽管我不确定为什么或如何。 最佳答案
弄清楚了。
*gQueueFamilyIndicesList = malloc(sizeof(QueueFamilyIndices) * queueFamilyCount);
现在可以正确分配内存并指向列表中的第一块内存。
这样取消引用和等同
(*gQueueFamilyIndicesList)[i] = gQueueFamilyIndices;
现在可以像我期望的那样工作。
gQueueFamilyIndicesList
周围的括号很重要,因为[]
运算符的优先级高于*
。*gQueueFamilyIndicesList[i]
= *(*(gQueueFamilyIndicesList + i))
和
(*gQueueFamilyIndicesList)[i]
= *((*gQueueFamilyIndicesList) + i)
关于c - Vulkan API和C-查询物理设备属性会导致segfault,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59876663/