Results 1 to 4 of 4

Thread: Best practice for vk rendering

  1. #1

    Best practice for vk rendering

    Hi,

    I have to render a scene graph where models share the same shader but with different materials data.
    The uniforms are stored in uniform buffer so when I render a model, I need to update this uniform buffer.

    For this purpose, my model class contain one descriptorSet and a list of commandBuffer with submitInfo.
    Init model :
    Code :
    create vertex/index buffer
    send texture data to GPU
    create or get instance of shader
    create descriptor set
    create command buffer
    create submitInfo

    The render loop :
    Code :
    submit command to clear
     
    foreach shaders :
        foreach models :
            update uniform data buffer
            submit submitInfo of this model
     
    submit command for sync
    presentKHR

    I'm not sure it's the best way to render complex scene, I'm beginner in vulkan.
    So what do you think about it ?

    Thank's,
    Stevens

  2. #2
    Senior Member
    Join Date
    Mar 2015
    Posts
    179
    append the new data to the uniform buffer and use a dynamic offset to point to the correct one.

    Code :
    vkBeginBuffer
    vkCmdStartRenderpass
    foreach shaders :
        vkCmdBindPipeline
        foreach models :
            append uniform data to buffer
            vkCmdBindDescriptorSets
            vkCmdDraw
    vkcmdEndRenderpass

  3. #3
    Thank's Ratchet Freak,

    I found that for dynamic offset : https://github.com/SaschaWillems/Vul...cuniformbuffer
    And for material texture per model, I use a second descriptor set :

    Code :
    // Alloc
    foreach shaders
        size = 0
        foreach models
            dynamicOffset = size
            size += sizeof(uniform)
     
        alloc ubo with size
        create descriptor set
     
    // Create command
    vkBeginBuffer
    vkCmdStartRenderpass
    foreach shaders :
        vkCmdBindPipeline
        foreach models :
            list<descriptorsSet> descriptors;
            descriptors.add(descriptorSetUBO)
     
            if(model.hasTexture)
                  descriptors.add(descriptorSetTexture)
     
            vkCmdBindDescriptorSets ( ...., descriptors.size(), descriptors.data(), 1, dynamicOffset )
            vkCmdDraw
    vkcmdEndRenderpass

    It look better than one descriptor set per model but that require more memory. Maybe push constant or cmdUpdateBuffers are better for large scene.
    Last edited by Stevens; 07-03-2018 at 05:25 AM.

  4. #4
    Senior Member
    Join Date
    Mar 2015
    Posts
    179
    The render code in your first post is very slow, you are ping ponging the execution so only one of the cpu and gpu is active at a time and most of the time they are waiting on the communication latency and cache flushing. You should instead try to give the gpu a lot of data to crunch through at a time. That way the communication latency is amortized between the render commands in the command buffer.

    You cannot cmdUpdateBuffers in the middle of a renderpass, so you need to put all the data in a buffer before you start the renderpass. Updating the pointer with vkCmdBindDescriptorSets is cheap, stopping and starting a renderpass is very expensive.

    pushconstants are tiny (128-256 bytes depending on the gpu) so there isn't a lot of data you can put in them. 2 mat4s already fills the 128 sized one up.

    don't be afraid to use multiple descriptor sets or bigger buffers when you need to, the memory used for the uniform data per mesh is tiny compared to the size of the mesh itself. A mat4 transform for 30 objects is just under 2 kilobytes.

    Your gpu will have GigaBytes worth of storage. So that uniform buffer is literally less than 0.0001% of all the memory you have in you GPU.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean