Reputation: 722
I have two different methods for adding elements to a vector.
GUI_Vertices.emplace_back();
GUI_Vertices.back().pos.x = ((float)x / 400) - 1.f;
GUI_Vertices.back().pos.y = ((float)y / 300) - 1.f;
GUI_Vertices.back().texCoord.x = u;
GUI_Vertices.back().texCoord.y = v;
GUI_Vertices.back().color.r = m_Color.r / 128;
GUI_Vertices.back().color.g = m_Color.g / 128;
GUI_Vertices.back().color.b = m_Color.b / 128;
GUI_Vertices.back().color.a = m_Color.a / 128;
The above code works, however I am forced to add a new element to the GUI_Vertices
vector.
Vertex NewVertex;
NewVertex.pos.x = ((float)x / 400) - 1.f;
NewVertex.pos.y = ((float)y / 300) - 1.f;
NewVertex.texCoord.x = u;
NewVertex.texCoord.y = v;
NewVertex.color.r = m_Color.r / 128;
NewVertex.color.g = m_Color.g / 128;
NewVertex.color.b = m_Color.b / 128;
NewVertex.color.a = m_Color.a / 128;
GUI_Vertices.emplace_back(NewVertex);
The above code works sometimes and I can conditionally add the NewVertex
into the GUI_Vertices
vector if needed.
Here is the definition of Vertex
:
struct Vertex {
glm::vec3 pos;
glm::vec4 color;
glm::vec2 texCoord;
static VkVertexInputBindingDescription getBindingDescription() {
VkVertexInputBindingDescription bindingDescription = {};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return bindingDescription;
}
static std::array<VkVertexInputAttributeDescription, 3> getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions = {};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Vertex, color);
attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2;
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
return attributeDescriptions;
}
bool operator==(const Vertex& other) const {
return pos == other.pos && color == other.color && texCoord == other.texCoord;
}
};
namespace std {
template<> struct hash<Vertex> {
size_t operator()(Vertex const& vertex) const {
return ((hash<glm::vec3>()(vertex.pos) ^
(hash<glm::vec4>()(vertex.color) << 1)) >> 1) ^
(hash<glm::vec2>()(vertex.texCoord) << 1);
}
};
}
Later on in program execution, after adding all our Vertex
elements to the GUI_Vertex
vector I perform the following operation on GUI_Vertex
:
memcpy(GUI_VertexAllocation->GetMappedData(), GUI_Vertices.data(), sizeof(Vertex) * GUI_Vertices.size());
I'm copying the memory from GUI_Vertices
into a preallocated buffer which will be used by Vulkan to render our vertices.
Now i'm trying to figure out why the first method of adding Vertex
objects into GUI_Vertices
always works and the second method only sometimes works.
Here is a link to the entire project https://github.com/kklouzal/WorldEngine/blob/GUI_Indirect_Draw/Vulkan/VulkanGWEN.hpp
After recompiling the project the second method will occasionally work so I'm getting some undefined behavior here. I have checked the validity of GUI_Vertices
up until the point where we do our memcpy
and the data appears to be valid so I'm not sure whats going on.
I would like to get the second method working so I can conditionally add new vertices into the buffer.
Upvotes: 1
Views: 277
Reputation: 473946
NewVertex.pos.x = ((float)x / 400) - 1.f; NewVertex.pos.y = ((float)y / 300) - 1.f; ... glm::vec3 pos;
emplace_back
will always perform value initialization on the object it creates, which initializes all of the data members. By contrast, Vertex NewVertex;
will default-initialize the object, which leaves its members uninitialized (since the GLM types have trivial default constructors).
So pos.z
is uninitialized. And your code doesn't initialize it yourself. So you're sending uninitialized garbage to the GPU.
If you create the object with Vertex NewVertex{};
, then it will be value-initialized, just like emplace_back
does.
Upvotes: 10