En supposant que vous appelez votre fonction comme ça :
vkInstance instance;
vkPhysicalDevice physicalDevice;
vkCreateInstance(..., &instance);
populatePhysicalDevice(&instance, &physicalDevice);
Ainsi, les deux valeurs des deux arguments passés sont les pointeurs vers instance
y physicalDevice
dans la portée de l'appelant. Les pointeurs (mais pas les valeurs qu'ils désignent) obtiennent copié dans les variables correspondantes dans populatePhysicalDevice
:
void populatePhysicalDevice(VkInstance* gInstance, VkPhysicalDevice* gPhysicalDevice)
{
Donc à ce stade, à l'intérieur populatePhysicalDevice()
vous avez deux pointeurs que vous pouvez modifier à volonté, mais qui ne changeront rien dans la portée de l'appelant. Continuons :
uint32_t physicalDeviceCount = 0;
vkEnumeratePhysicalDevices(*gInstance, &physicalDeviceCount, VK_NULL_HANDLE);
VkPhysicalDevice physicalDevices[physicalDeviceCount];
vkEnumeratePhysicalDevices(*gInstance, &physicalDeviceCount, physicalDevices);
Maintenant vous avez un tableau local de VKPhysicalDevice
qui a été remplacée par vkEnumeratePhysicalDevices()
. Vous voulez maintenant vous assurer que l'appelant reçoit une copie du dispositif physique le mieux adapté :
int bestSuitedPhysicalDeviceLocation = 0;
gPhysicalDevice = &physicalDevices[bestSuitedPhysicalDeviceLocation]; // Causes segfault
Cette ligne ne fait rien que l'appelant puisse voir. Elle va juste changer la variable locale gPhysicalDevice
pour pointer vers le début du tableau local physicalDevices
. Quand vous revenez, toutes ces choses disparaissent. Le résultat final est que [hysicalDevice
dans la portée de l'appelant n'a pas été initialisé. C'est la cause probable de l'erreur de segmentation.
Quand vous faites ça à la place :
*gPhysicalDevice = physicalDevices[bestSuitedPhysicalDeviceLocation]; // Works
En fait, vous copiez la valeur du premier élément de l'élément physicalDevices[]
dans la variable physicalDevice
dans la portée de l'appelant.
Notez que si vous allez toujours chercher le premier dispositif physique, vous n'avez pas besoin de créer un tableau local, vous pouvez simplement le faire :
void populatePhysicalDevice(VkInstance* gInstance, VkPhysicalDevice* gPhysicalDevice)
{
vkEnumeratePhysicalDevices(*gInstance, 1, gPhysicalDevices);
}
Mais n'oubliez pas que l'instance peut ne pas avoir de dispositifs physiques disponibles. Vérifiez donc les valeurs de retour des fonctions que vous appelez et assurez-vous qu'elles sont conformes aux attentes !