Hi, I create a vertex buffer an I copy it into a std::vector.
He calls the destructor of my vertex buffer class on this function :
void RenderTarget::createUniformBuffers() {
VkDeviceSize bufferSize = sizeof(UniformBufferObject);
std::vector<VkBuffer> ubos;
std::vector<VkDeviceMemory> ubosMemory;
ubos.resize(getMaxFramesInFlight());
ubosMemory.resize(getMaxFramesInFlight());
for (size_t i = 0; i < getMaxFramesInFlight(); i++) {
createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, ubos[i], ubosMemory[i]);
}
uniformBuffers.push_back(ubos);
uniformBuffersMemory.push_back(ubosMemory);
VertexBuffer vb(vkDevice);
vertexBuffers.push_back(vb);
}
But it tells me that the adress of the vertex buffer is invalid in the vkDestroy function or I don’t create the vertex buffer because I only create the vertex buffer in the update function of my vertex buffer class so it should be null but he’s not null but he have a strange adress :
VertexBuffer::VertexBuffer(window::Device& vkDevice) : vkDevice(vkDevice), vertexBufferCreated(false), indexBufferCreated(false),
needToUpdateVertexBuffer(false), needToUpdateIndexBuffer(false) {
createCommandPool();
}
void VertexBuffer::clear() {
m_vertices.clear();
}
void VertexBuffer::clearIndexes() {
indices.clear();
}
void VertexBuffer::addIndex(uint16_t index) {
indices.push_back(index);
needToUpdateIndexBuffer = true;
}
void VertexBuffer::append(const Vertex& vertex) {
m_vertices.push_back(vertex);
needToUpdateVertexBuffer = true;
}
void VertexBuffer::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(vkDevice.getDevice(), &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create buffer!");
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(vkDevice.getDevice(), buffer, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
if (vkAllocateMemory(vkDevice.getDevice(), &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate buffer memory!");
}
vkBindBufferMemory(vkDevice.getDevice(), buffer, bufferMemory, 0);
}
void VertexBuffer::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = commandPool;
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(vkDevice.getDevice(), &allocInfo, &commandBuffer);
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
VkBufferCopy copyRegion{};
copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region);
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(vkDevice.getGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(vkDevice.getGraphicsQueue());
vkFreeCommandBuffers(vkDevice.getDevice(), commandPool, 1, &commandBuffer);
}
uint32_t VertexBuffer::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(vkDevice.getPhysicalDevice(), &memProperties);
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
return i;
}
}
throw std::runtime_error("aucun type de memoire ne satisfait le buffer!");
}
VkBuffer VertexBuffer::getVertexBuffer() {
return vertexBuffer;
}
size_t VertexBuffer::getSize() {
return m_vertices.size();
}
size_t VertexBuffer::getVertexCount() {
return m_vertices.size();
}
size_t VertexBuffer::getIndicesSize() {
return indices.size();
}
VkBuffer VertexBuffer::getIndexBuffer() {
return indexBuffer;
}
////////////////////////////////////////////////////////////
void VertexBuffer::setPrimitiveType(PrimitiveType type)
{
m_primitiveType = type;
}
////////////////////////////////////////////////////////////
PrimitiveType VertexBuffer::getPrimitiveType() const
{
return m_primitiveType;
}
void VertexBuffer::update() {
if (needToUpdateVertexBuffer) {
VkDeviceSize bufferSize = sizeof(Vertex) * m_vertices.size();
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(vkDevice.getDevice(), stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, m_vertices.data(), (size_t) bufferSize);
vkUnmapMemory(vkDevice.getDevice(), stagingBufferMemory);
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
vkDestroyBuffer(vkDevice.getDevice(), stagingBuffer, nullptr);
vkFreeMemory(vkDevice.getDevice(), stagingBufferMemory, nullptr);
vertexBufferCreated = true;
needToUpdateVertexBuffer = false;
}
if (needToUpdateIndexBuffer) {
VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(vkDevice.getDevice(), stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, indices.data(), (size_t) bufferSize);
vkUnmapMemory(vkDevice.getDevice(), stagingBufferMemory);
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
copyBuffer(stagingBuffer, indexBuffer, bufferSize);
vkDestroyBuffer(vkDevice.getDevice(), stagingBuffer, nullptr);
vkFreeMemory(vkDevice.getDevice(), stagingBufferMemory, nullptr);
indexBufferCreated = true;
needToUpdateIndexBuffer = false;
}
}
Vertex& VertexBuffer::operator [](unsigned int index)
{
return m_vertices[index];
}
void VertexBuffer::createCommandPool() {
window::Device::QueueFamilyIndices queueFamilyIndices = vkDevice.findQueueFamilies(vkDevice.getPhysicalDevice(), VK_NULL_HANDLE);
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // Optionel
if (vkCreateCommandPool(vkDevice.getDevice(), &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
throw core::Erreur(0, "échec de la création d'une command pool!", 1);
}
}
VertexBuffer::~VertexBuffer() {
/*if (indexBufferCreated) {
vkDestroyBuffer(vkDevice.getDevice(), indexBuffer, nullptr);
vkFreeMemory(vkDevice.getDevice(), indexBufferMemory, nullptr);
}
if (vertexBufferCreated) {
vkDestroyBuffer(vkDevice.getDevice(), vertexBuffer, nullptr);
vkFreeMemory(vkDevice.getDevice(), vertexBufferMemory, nullptr);
}*/
}
Even if I initialize the vkBuffer to null he’s not null in the destructor…
Why ?
Tanks.