when creating some vulkan objects like VkCommandBufferAllocateInfo,it is required to zero-initialize them first.This is error-prone,so how do I auto zero-initialize them in c++ code?
Nothing requires this. What is required is that the struct be properly initialized by the time the Vulkan implementation sees it. If “zero-initializing them first” is the only way to make your code work, that’s probably because you’re not correctly initializing all of the members.
But if you want to ensure that a basic struct is zero-initialized, you can wrap it in a type that has a default constructor which zero-initializes the member:
template<typename T>
struct zinit
{
T value;
zinit() value{} {}
};
This is not especially useful though. Since most Vulkan structs have an sType member that must be initialized to a specific value (as in VkCommandBufferAllocateInfo value = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};), you’re going to have to do that manually (or write a code generator based on the Vulkan standard that creates the code for you). So there’s not much to be gained, since you need to properly initialize the object anyway.
But I can remember I did encounter the situation in which I only forgot to put “{}” when initializing struct like VkDescriptorPoolCreateInfo,and my program crashed after that.And is that only because like what you said “because I’m not correctly initializing all of the members.”?
I used this template code in my own code,it just seems to be too cumbersome:
namespace Vk
{
template<typename T>
struct VkCI
{
T value;
VkCI():value{} {}
};
}
Vk::VkCI<VkDescriptorPoolCreateInfo> descriptor_pool_CI;
descriptor_pool_CI.value.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
I also notice in Sascha Willems’s vulkan example,he uses functions to do this initialization which makes code even more hard to read.
Can I just copy and paste all the structs defined in vulkan_core.h file and provide some fields of those structs with default values?What’s the pros and cons of doing this?
And thanks for your patience, Alfonse Reinheart.
I had to find a balance between too much and too little abstraction, that’s why it may not seem too intuitive for your use-case.
But there’s no need to copy what I did.
If I were to redo it, I would generate an initializer library from the Vulkan XML registry. I use that XML in different places to generate code (e.g. Vulkan Hardware Capability Viewer and the database) and it has all the info you need.
E.g.:
<type category="struct" name="VkInstanceCreateInfo">
<member values="VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkInstanceCreateFlags</type> <name>flags</name></member>
<member optional="true">const <type>VkApplicationInfo</type>* <name>pApplicationInfo</name></member>
<member optional="true"><type>uint32_t</type> <name>enabledLayerCount</name></member>
<member len="enabledLayerCount,null-terminated">const <type>char</type>* const* <name>ppEnabledLayerNames</name><comment>Ordered list of layer names to be enabled</comment></member>
<member optional="true"><type>uint32_t</type> <name>enabledExtensionCount</name></member>
<member len="enabledExtensionCount,null-terminated">const <type>char</type>* const* <name>ppEnabledExtensionNames</name><comment>Extension names to be enabled</comment></member>
</type>
This can easily be parsed into your own initializing stuff.
Or if you don’t mind you could always use vulkan.hpp, which does all that initialization stuff for you.