1

I am found a bug in my code, that cause mesh data corruption in certain situation using staging buffer. I have:

  1. temporary mesh data

  2. staging buffer with certain size, that used simultaneously by command buffer and memcpy, but not same segment at a time.

  3. Buffer allocator, that gives part of suitable vertex-index buffer, where mesh data transfers from staging by vkCmdCopyBuffer. Buffer contains many of segments, given for different meshes.

The issue that when I am using staging buffer simultaneously by command buffer and memcpy, mesh data writes incorrectly (become overwritten/corrupted) and even badly can cause VK_ERROR_DEVICE_LOST .

https://i.sstatic.net/xluPf.jpg "correct mesh"

https://i.sstatic.net/aW949.jpg "broken mesh"

    [[nodiscard]] static Result writeMeshBuffer(TransferData &data, GpuMesh &buffer)
    {
        Result result; using namespace vkw;

        auto &mesh = buffer.source;

        size_t vSize = mesh.vertices_count * mesh.vertex_size;
        size_t iSize = mesh.indices_count  * mesh.index_size;
        size_t mesh_size = vSize + iSize;

        auto &staging_offset = data.stagingData.buffer_offset_unused;

        // write data to staging buffer
        {
            // guaranteed that mesh_size will less or equal than staging buffer size
            //FIXME false condition generate broken meshes somehow
            bool is_wait_before = mesh_size > TransferStagingData::BUFFER_SIZE - staging_offset;
            //will work correctly:
            //bool is_wait_before = true;

            if (is_wait_before) // if we need more memory on staging buffer than not used already
            {
                result = data.wait_transfer();
                if (result != VK_SUCCESS)
                    return result;
                staging_offset = 0;
            }

            uint8_t *pMemory = static_cast<uint8_t*>(data.stagingData.pMemory) + staging_offset;

            memcpy(pMemory,         mesh.vertices.pX, vSize);
            memcpy(pMemory + vSize, mesh.indices.pXX, iSize);

            if (not is_wait_before)
            {
                result = data.wait_transfer();
                if (result != VK_SUCCESS)
                    return result;
            }
        }

        // write data from staging buffer to mesh buffer
        {
            auto cmd_cpy_buff = [](CommandBuffer cmd, BufferCopy copy, Offsets offsets, DeviceSizeT size)
            {
                cmd.cmd_copy_buffer(copy, offsets, size);
            };

                                       //       SRC                                 DST
            BufferCopy copy = { data.stagingData.buffer, buffer.info.buffer        };
            Offsets offsets = { staging_offset,          buffer.info.region.offset };
            result = data.transfer.prepare(cmd_cpy_buff, data.transfer.cmd_buffer, copy, offsets, mesh_size);
            if (result != VK_SUCCESS)
                return result;

            data.reset_fence();

            result = data.transfer.submit({&data.transfer.cmd_buffer,1},{}, {}, {}, data.transferFence);
            if (result != VK_SUCCESS)
                return result;
        }

        // save usused offset to  data.stagingData.buffer_offset_unused;
        staging_offset = staging_offset == 0 ? mesh_size : 0;

        return result;
    }

If I can't use staging buffer like this, than why.

If i have an error, idk where.

1 Answer 1

1

The issue was

staging_offset = staging_offset == 0 ? mesh_size : 0;

Need to change

staging_offset = staging_offset == 0 ? TransferStagingData::BUFFER_SIZE - mesh_size : 0;

And after change all works correctly.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.