#How would you reload a scene?

80 messages · Page 1 of 1 (latest)

manic gorge
#

I am close to implementing runtime model loading on my own, however I am stuck with the issue of vertex and index buffers being consumed by the command buffer as they are bound to it by vkBindVertexBuffers() and vkBindIndexBuffer(), is there a way to update the vertex and index buffer without recreating it, or am I going towards the wrong path in reloading a scene?

hollow kestrel
#

For reloading a scene, you can wait for the GPU to finish using the vertex buffers before updating them. Obviously that'll make you wait for stuff, but it probably won't matter since reloading a scene doesn't happen often.

If you're trying to stream in models dynamically without frame hitches, I think you can still access areas of vertex buffers that aren't currently in use, which works great if you have the "one big vertex buffer" approach. If you're creating vertex buffers per model, you can make a new vertex buffer for the new model, upload stuff to it, and replace it in the next frame when it's ready. The old model can then go on a deletion queue to get deleted and freed when the GPU is done with it.

If you're updating this stuff each frame, then you should just double buffer it.

manic gorge
#

I got vkDeviceIdle on my reload

#

is that software or gpu based

#

nvm it uses the logical device

hollow kestrel
#

vkDeviceWaitIdle will wait for the GPU to finish everything.

manic gorge
#

but i still don't get why i get a validation error from it

hollow kestrel
#

You're getting a validation error from the wait idle?

manic gorge
#

i got this ```cpp
Validation Error: [ VUID-vkDestroyBuffer-buffer-00922 ] Object 0: handle = 0x25b2cf8c990, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xe4549c11 | Cannot call vkDestroyBuffer on VkBuffer 0xf6d9250000000139[] that is currently in use by a command buffer. The Vulkan spec states: All submitted commands that refer to buffer, either directly or via a VkBufferView, must have completed execution (https://vulkan.lunarg.com/doc/view/1.3.224.1/windows/1.3-extensions/vkspec.html#VUID-vkDestroyBuffer-buffer-00922)

#

then this ```cpp
Validation Error: [ VUID-vkCmdBindDescriptorSets-pDescriptorSets-01979 ] Object 0: handle = 0x25b2ce96b00, name = FRAME COMMAND BUFFER, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0xb9b24e0000000113, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; Object 2: handle = 0x35643f0000000111, name = DYNAMIC UNIFORM, type = VK_OBJECT_TYPE_BUFFER; | MessageID = 0xa159a763 | vkCmdBindDescriptorSets(): pDynamicOffsets[0] is 0x40 which when added to the buffer descriptor's range (0x40) is greater than the size of the buffer (0x40) in descriptorSet #0 binding #1 descriptor[0]. The Vulkan spec states: For each dynamic uniform or storage buffer binding in pDescriptorSets, the sum of the effective offset and the range of the binding must be less than or equal to the size of the buffer (https://vulkan.lunarg.com/doc/view/1.3.224.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdBindDescriptorSets-pDescriptorSets-01979)

Validation Error: [ VUID-vkCmdDrawIndexed-firstIndex-04932 ] Object 0: handle = 0x2c9fc9000000010f, name = INDEX BUFFER, type = VK_OBJECT_TYPE_BUFFER; | MessageID = 0x20509750 | vkCmdDrawIndexed(): index size (4) * (firstIndex (786801) + indexCount (19188)) + binding offset (0) = an ending offset of 3223956 bytes, which is greater than the index buffer size (3147204). The Vulkan spec states: (indexSize {times} (firstIndex + indexCount) + offset) must be less than or equal to the size of the bound index buffer, with indexSize being based on the type specified by indexType, where the index buffer, indexType, and offset are specified via vkCmdBindIndexBuffer (https://vulkan.lunarg.com/doc/view/1.3.224.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdDrawIndexed-firstIndex-04932)

hollow kestrel
#

For the first one, how are you destroying the buffer? What's your code for the scene reload?

manic gorge
#

that one is related to my viewport resizing which i have not found the root of yet, but the second one is related to my reload scene

#

which looks like this

#
void Adren::Renderer::reloadScene(std::vector<Model>& models, Camera* camera) {
    /*
        This function would be the basis of model loading, as buffers and descriptors get updated
        when there is a new model. This is experimental and may be causing lots of performance issues

        What this does is re-render the entire screen when new elements are in. 
    */

    vkDeviceWaitIdle(devices.device);

    vmaDestroyBuffer(devices.allocator, buffers.index.buffer, buffers.index.memory);
    vmaDestroyBuffer(devices.allocator, buffers.vertex.buffer, buffers.vertex.memory);
    vmaUnmapMemory(devices.allocator, buffers.dynamicUniform.memory);

    for (const Model::Texture& texture : textures) {
        vmaDestroyImage(devices.allocator, texture.image, texture.memory);
        vkDestroyImageView(devices.device, texture.view, nullptr);
    }
    textures.clear();

    images.loadTextures(instance, models, textures, processing.commandPool);
    buffers.createModelBuffers(models, processing.commandPool);

    buffers.createUniformBuffers(swapchain.images, models);

    descriptor.createSets(textures, swapchain.images, camera->cam);
}
#

basically i am destroying the vertex, index and dynamic uniform buffer, destroying the textures and then reloading the textures, recreating the vertex, index, and dynamic uniform buffer while also updating the descriptor sets.

hollow kestrel
#

Ok. What does createModelBuffers look like?

manic gorge
# hollow kestrel Ok. What does createModelBuffers look like?
void Adren::Buffers::createModelBuffers(std::vector<Model>& models, VkCommandPool& commandPool) {
    std::vector<Vertex> vertices;
    std::vector<uint32_t> indices;

    for (auto& model : models) {
        indices.insert(indices.end(), model.indices.begin(), model.indices.end());
        vertices.insert(vertices.end(), model.vertices.begin(), model.vertices.end());
    }

    vertex.size = sizeof(vertices[0]) * vertices.size();
    Buffer vStaging;
    createBuffer(allocator, vertex.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
        VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vStaging, VMA_MEMORY_USAGE_AUTO);

    vmaMapMemory(allocator, vStaging.memory, &vStaging.mapped);
    memcpy(vStaging.mapped, vertices.data(), (size_t)vertex.size);
    vmaUnmapMemory(allocator, vStaging.memory);

    createBuffer(allocator, vertex.size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertex, VMA_MEMORY_USAGE_AUTO);

    copyBuffer(vStaging.buffer, vertex.buffer, vertex.size, commandPool);

    vmaDestroyBuffer(allocator, vStaging.buffer, vStaging.memory);

    index.size = sizeof(indices[0]) * indices.size();

    Buffer iStaging;
    createBuffer(allocator, index.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
        VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, iStaging, VMA_MEMORY_USAGE_AUTO);

    vmaMapMemory(allocator, iStaging.memory, &iStaging.mapped);
    memcpy(iStaging.mapped, indices.data(), (size_t)index.size);
    vmaUnmapMemory(allocator, iStaging.memory);

    createBuffer(allocator, index.size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, index, VMA_MEMORY_USAGE_AUTO);
    copyBuffer(iStaging.buffer, index.buffer, index.size, commandPool);

    vmaDestroyBuffer(allocator, iStaging.buffer, iStaging.memory);

#ifdef DEBUG
    Adren::Tools::label(instance, device, VK_OBJECT_TYPE_BUFFER, (uint64_t)vertex.buffer, "VERTEX BUFFER");
    Adren::Tools::label(instance, device, VK_OBJECT_TYPE_BUFFER, (uint64_t)index.buffer, "INDEX BUFFER");
#endif
}
hollow kestrel
#

Ok, what's createBuffer and copyBuffer? Trying to get down to the Vulkan calls here.

manic gorge
# hollow kestrel Ok, what's createBuffer and copyBuffer? Trying to get down to the Vulkan calls h...
void Adren::Buffers::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size, VkCommandPool& commandPool) {
    VkCommandBuffer commandBuffer = Adren::Tools::beginSingleTimeCommands(device, commandPool);

    VkBufferCopy copyRegion{};
    copyRegion.size = size;
    vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);

    Adren::Tools::endSingleTimeCommands(commandBuffer, device, graphicsQueue, commandPool);
}

void Adren::Buffers::createBuffer(VmaAllocator& allocator, VkDeviceSize& size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, Buffer& buffer, VmaMemoryUsage vmaUsage) {
    VkBufferCreateInfo bufferInfo{};
    bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    bufferInfo.size = size;
    bufferInfo.usage = usage;
    bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

    VmaAllocationCreateInfo vmaAllocInfo{};
    vmaAllocInfo.usage = vmaUsage;
    vmaAllocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
    vmaAllocInfo.preferredFlags = properties;

    vmaCreateBuffer(allocator, &bufferInfo, &vmaAllocInfo, &buffer.buffer, &buffer.memory, nullptr);
}
hollow kestrel
#

What's the code where the vkCmdDrawIndexed fails?

#

It seems that for that one you're passing the size of the index buffer as first index.

manic gorge
#

oh

#

it appears i may have to update firstindex

#

cause what i am doing is trying to load this model

#

with sponza

#

I already have sponza loaded at start up, i just want to load this one while it is running

hollow kestrel
#

Oh, were you still having issues with this?

manic gorge
#

yes

#

still

hollow kestrel
#

What are the errors after you fixed the first index thing?

manic gorge
#

i still haven't fixed it

#

actually i've not been getting it

hollow kestrel
#

What validation errors are you getting now then?

manic gorge
#

sorry for the very late response, but I am a bit busy with university, and I kinda messed up my engine again by rewriting a bunch of code. I am currently decoupling a class and putting the function of it in the main renderer class but I am a bit busy to continue working on it.

manic gorge
#

@hollow kestrel sorry for the delay, but I finally was able to continue working on it and get it running again. However here is the validation errors I get.

Reloading the scene..


Validation Error: [ VUID-vkDestroyBuffer-buffer-00922 ] Object 0: handle = 0x2b10d969de0, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xe4549c11 | Cannot call vkDestroyBuffer on VkBuffer 0x2c9fc9000000010f[INDEX BUFFER] that is currently in use by a command buffer. The Vulkan spec states: All submitted commands that refer to buffer, either directly or via a VkBufferView, must have completed execution (https://vulkan.lunarg.com/doc/view/1.3.224.1/windows/1.3-extensions/vkspec.html#VUID-vkDestroyBuffer-buffer-00922)


Index buffer destroyed..


Validation Error: [ VUID-vkDestroyBuffer-buffer-00922 ] Object 0: handle = 0x2b10d969de0, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xe4549c11 | Cannot call vkDestroyBuffer on VkBuffer 0x4d6d9a000000010c[VERTEX BUFFER] that is currently in use by a command buffer. The Vulkan spec states: All submitted commands that refer to buffer, either directly or via a VkBufferView, must have completed execution (https://vulkan.lunarg.com/doc/view/1.3.224.1/windows/1.3-extensions/vkspec.html#VUID-vkDestroyBuffer-buffer-00922)


Vertex buffer destroyed..


Dynamic uniform buffer destroyed..


Validation Error: [ VUID-vkDestroyImage-image-01000 ] Object 0: handle = 0x2b10d969de0, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xf2d29b5a | Cannot call vkDestroyImage on VkImage 0x301e6c0000000022[TEXTURE IMAGE] that is currently in use by a command buffer. The Vulkan spec states: All submitted commands that refer to image, either directly or via a VkImageView, must have completed execution (https://vulkan.lunarg.com/doc/view/1.3.224.1/windows/1.3-extensions/vkspec.html#VUID-vkDestroyImage-image-01000)


Textures destroyed..
#

So somehow vkdevicewaitidle was no longer in the function so all these errors are gone

#

but i still have a memory issue

#

where it tries to map the textures but fails even though the previous textures are already deallocated

hollow kestrel
hollow kestrel
manic gorge
#

visual studio just stops it during the part where i am copying the image data to a memory buffer

hollow kestrel
#

Stops it how? Does it hit a segfault, freeze, break?

#

What's the code around the image data copying?

manic gorge
# hollow kestrel Stops it how? Does it hit a segfault, freeze, break?

it just crashes after i press import model then picked a file. Doing that adds it to my model vector and then I have a object counter that an if statement is checking if the model vector's size is greater than it, if so then the object counter gets updated and then reloadScene() is called, it manages to destroy everything but the error comes from re-creating it.

hollow kestrel
#

I'm still not really sure what sort of crash this is. Does it segfault or hit a debug assert or validation error or what? Would you post the code for recreating your images and show the part that actually crashes?

manic gorge
#

Alright

manic gorge
#

@hollow kestrel

#

no validation errors

hollow kestrel
#

Ok, so it segfaults trying to read image data. Make sure that image actually exists before using it.

#

Have you got this code on github by any chance? It would be much easier to debug if I could see the code leading up to this.

manic gorge
#

I do have it on github but i have the bad habit of not committing so I am going to do that now

manic gorge
#

the textures are loaded in images

#

i was gonna decouple it but forgot to 🤦

#

anyways this is the model i was trying to load in

hollow kestrel
#

Ok, I've looked at the code for a while. While I haven't checked to make sure, I'd be worried about this code in Model::getTextures. If the model gets copied, I think the the GLTF vector might change while the pointer into it doesn't. I could be missing something though, like I said, I haven't actually tested.

manic gorge
#

hmm

hollow kestrel
#

The sponza one would have worked because that one stays in the class and still exists, but anything loaded with the model load method allocates a model on the stack first.

manic gorge
#

oh

#

so what should i do then

hollow kestrel
#

You could take the address from the image data vector every time you copy from it. You could also take it again in a copy constructor/assignment. You could also implement a move constructor/assignment and use that when putting the model in the vector (though I'm not sure if the vector data is guaranteed to be the same after a move).

#

Whatever you do, the pointer has to actually point to the texture memory when you copy it to the staging buffer.

manic gorge
#

I made it a pointer but still getting the same error.

#

What if I made the model itself a pointer?

manic gorge
#

alright that solved the image issue but now i have this

#

VULKAN ERROR FOR ALLOCATED DESCRIPTOR SETS: -1000069000

#

which is VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000

#

how do i allocate more

manic gorge
#

so i made my descriptor pool have 100,000 size

#

and set the max sets to 200

#

now i get this kaleidoscope

#

At least I am not crashing

hollow kestrel
#

Yeah, I've had lots of those when screwing up my vertex data or vertex formats.

manic gorge
#

I rooted the problem to textures, according to render doc the vertices and indices have loaded properly

hollow kestrel
#

Why would textures cause the geometry to go crazy like that?

manic gorge
#

actually after further diagnosis in renderdoc it was geometry

#

the vertex shader input is right but the output is not

manic gorge
#

Let's go! I finally got it working. All I forgot to do was update the buffer.