在哪些情况下可以在堆栈上分配
In which cases is it okay to allocate on the stack
我目前正在学习 Vulkan。在学习几个教程的过程中,反复出现大致相同的代码:
VkInstance g_instance;
void SetupVulkan(){
VkApplicationInfo appInfo = {};
//Set appInfo attributes
VkInstanceCreateInfo instanceInfo = {};
instanceInfo.pApplicationInfo = &appInfo;
//Set ICI attributes
VkResult result = vkCreateInstance(&instanceInfo, NULL, &g_instance);
//Error handling
}
这会在堆栈上创建一个 VkApplicationInfo
和一个 VkInstanceCreateInfo
。当离开函数并使用 g_instance
时,这不会导致一些问题吗? vkCreateInstance
是否复制了 VkApplicationInfo
和 VkInstanceCreateInfo
的所有数据?如果是这样,那么官方手册为什么不告诉我这种行为呢? https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCreateInstance.html
相同的模式在整个 API 中重复出现。我如何找出在哪些情况下堆栈上的分配是好的,在哪些情况下应该首选更持久的方式,如堆或全局内存?
重要的是要记住哪些对象代表您向 Vulkan 提供数据,哪些对象代表 Vulkan 对象或 Vulkan 向您返回数据。
VkInstance
是 Vulkan 句柄。这意味着它实际上是一个指针或 64 位整数或类似的东西。您将它用作指向对象的指针,而不是对象本身。所以它在功能上与此没有什么不同:
Type *p
auto error_code = getPtr(&p);
return p;
Vulkan 创建的所有对象(即:vkCreate
或 vkAllocate
调用的结果)都是句柄。它们都像 pointers/references,因此您可以放心地随意传递它们。
实际的 Vulkan 结构,如各种 Info
对象,用于 Vulkan 的输入或 Vulkan 的输出。但无论哪种方式,Vulkan 都只会在函数调用期间使用它们。所以你之后如何处理它们完全取决于你。
甚至像 VkPhysicalDeviceFeatures
这样的输出数据结构仍然只是 C++ 结构。您可以以 C++ 允许的任何方式使用它们。它们中的数据没有额外的引用或指向 Vulkan 拥有的内存的指针;它们只是一堆值。
如果您使用 VkAllocationCallbacks
,则需要小心。该实现将在内部存储存储在该结构中的指针。所以它们需要保持有效,直到您销毁关联的对象。但是结构本身不会在您给它的 Vulkan 调用持续时间之外存储。
If so, then why doesn't the official manual tell me about this behavior?
确实如此,在第 2.3.1 节中。这适用于 Vulkan 规范中的每个函数,因此不会在每个函数中单独列出:
Application-owned memory is immediately consumed by any Vulkan command it is passed into. The application can alter or free this memory as soon as the commands that consume it have returned.
我目前正在学习 Vulkan。在学习几个教程的过程中,反复出现大致相同的代码:
VkInstance g_instance;
void SetupVulkan(){
VkApplicationInfo appInfo = {};
//Set appInfo attributes
VkInstanceCreateInfo instanceInfo = {};
instanceInfo.pApplicationInfo = &appInfo;
//Set ICI attributes
VkResult result = vkCreateInstance(&instanceInfo, NULL, &g_instance);
//Error handling
}
这会在堆栈上创建一个 VkApplicationInfo
和一个 VkInstanceCreateInfo
。当离开函数并使用 g_instance
时,这不会导致一些问题吗? vkCreateInstance
是否复制了 VkApplicationInfo
和 VkInstanceCreateInfo
的所有数据?如果是这样,那么官方手册为什么不告诉我这种行为呢? https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkCreateInstance.html
相同的模式在整个 API 中重复出现。我如何找出在哪些情况下堆栈上的分配是好的,在哪些情况下应该首选更持久的方式,如堆或全局内存?
重要的是要记住哪些对象代表您向 Vulkan 提供数据,哪些对象代表 Vulkan 对象或 Vulkan 向您返回数据。
VkInstance
是 Vulkan 句柄。这意味着它实际上是一个指针或 64 位整数或类似的东西。您将它用作指向对象的指针,而不是对象本身。所以它在功能上与此没有什么不同:
Type *p
auto error_code = getPtr(&p);
return p;
Vulkan 创建的所有对象(即:vkCreate
或 vkAllocate
调用的结果)都是句柄。它们都像 pointers/references,因此您可以放心地随意传递它们。
实际的 Vulkan 结构,如各种 Info
对象,用于 Vulkan 的输入或 Vulkan 的输出。但无论哪种方式,Vulkan 都只会在函数调用期间使用它们。所以你之后如何处理它们完全取决于你。
甚至像 VkPhysicalDeviceFeatures
这样的输出数据结构仍然只是 C++ 结构。您可以以 C++ 允许的任何方式使用它们。它们中的数据没有额外的引用或指向 Vulkan 拥有的内存的指针;它们只是一堆值。
如果您使用 VkAllocationCallbacks
,则需要小心。该实现将在内部存储存储在该结构中的指针。所以它们需要保持有效,直到您销毁关联的对象。但是结构本身不会在您给它的 Vulkan 调用持续时间之外存储。
If so, then why doesn't the official manual tell me about this behavior?
确实如此,在第 2.3.1 节中。这适用于 Vulkan 规范中的每个函数,因此不会在每个函数中单独列出:
Application-owned memory is immediately consumed by any Vulkan command it is passed into. The application can alter or free this memory as soon as the commands that consume it have returned.