diff --git a/Examples/RenderingBenchmark/CMakeLists.txt b/Examples/RenderingBenchmark/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b11f6bc47e3bcdd345b387b25921df6ebe4c854e
--- /dev/null
+++ b/Examples/RenderingBenchmark/CMakeLists.txt
@@ -0,0 +1,35 @@
+###########################################################################
+#
+# Copyright (c) Kitware, Inc.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0.txt
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+###########################################################################
+
+project(Example-RenderingBenchmark)
+
+#-----------------------------------------------------------------------------
+# Create executable
+#-----------------------------------------------------------------------------
+add_executable(${PROJECT_NAME} RenderingBenchmark.cpp)
+
+#-----------------------------------------------------------------------------
+# Add shaders
+#-----------------------------------------------------------------------------
+include(imstkCopyAndCompileShaders)
+CopyAndCompileShaders()
+
+#-----------------------------------------------------------------------------
+# Link libraries to executable
+#-----------------------------------------------------------------------------
+target_link_libraries(${PROJECT_NAME} SimulationManager)
\ No newline at end of file
diff --git a/Examples/RenderingBenchmark/RenderingBenchmark.cpp b/Examples/RenderingBenchmark/RenderingBenchmark.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cfff4b781061b53edfc68a59dac263071676a4e9
--- /dev/null
+++ b/Examples/RenderingBenchmark/RenderingBenchmark.cpp
@@ -0,0 +1,146 @@
+/*=========================================================================
+
+   Library: iMSTK
+
+   Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+   & Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+=========================================================================*/
+
+#include "imstkSimulationManager.h"
+#include "imstkMeshIO.h"
+#include "imstkPbdObject.h"
+#include "imstkPbdSolver.h"
+#include "imstkOneToOneMap.h"
+#include "imstkAPIUtilities.h"
+#include "imstkLineMesh.h"
+
+using namespace imstk;
+
+///
+/// \brief This benchmark is to test the speed of various rendering operations
+///
+int main()
+{
+    // SDK and Scene
+    auto sdk = std::make_shared<SimulationManager>();
+    auto scene = sdk->createNewScene("RenderingBenchmarkTest");
+
+    auto camera = scene->getCamera();
+    camera->setPosition(0, 0, 1);
+    camera->setFocalPoint(0, 0, -1);
+
+    int numMeshes = 2000;
+    std::cout << "Enter number of meshes: ";
+    std::cin >> numMeshes;
+
+    size_t numLines = 100;
+    std::cout << "Enter number of triangles: ";
+    std::cin >> numLines;
+
+    bool dynamicMesh = true;
+    std::cout << "Enter dynamic mesh: ";
+    std::cin >> dynamicMesh;
+
+    std::vector<LineMesh::LineArray> lines;
+    StdVectorOfVec3d vertices;
+
+    vertices.resize(numLines * 2);
+    lines.resize(numLines);
+
+    for (int i = 0; i < numLines; i++)
+    {
+        vertices[i * 2] = Vec3d(0, 0, 0);
+        vertices[i * 2 + 1] = Vec3d(0, 0, 0.1);
+        lines[i][0] = i * 2;
+        lines[i][1] = i * 2 + 1;
+    }
+
+    for (int j = 0; j < numMeshes; j++)
+    {
+        // Construct surface mesh
+        auto mesh = std::make_shared<LineMesh>();
+
+        mesh->initialize(vertices, lines);
+
+        if (dynamicMesh)
+        {
+            auto object = std::make_shared<PbdObject>(std::string("mesh") + std::to_string(j));
+            object->setVisualGeometry(mesh);
+
+            auto model = std::make_shared<PbdModel>();
+            model->setModelGeometry(mesh);
+            object->setDynamicalModel(model);
+            scene->addSceneObject(object);
+        }
+        else
+        {
+            auto object = std::make_shared<VisualObject>(std::string("mesh") + std::to_string(j));
+            object->setVisualGeometry(mesh);
+            scene->addSceneObject(object);
+        }
+
+    }
+
+    int frame = 0;
+    auto watch = std::make_shared<StopWatch>();
+    auto startWatch = std::make_shared<StopWatch>();
+    double endTime = 0;
+    int startFrame = -1;
+    int startupFrame = -1;
+
+    sdk->getViewer()->setOnTimerFunction([&](InteractorStyle* c) -> bool
+        {
+            if (dynamicMesh)
+            {
+                for (int j = 0; j < numMeshes; j++)
+                {
+                    auto object = scene->getSceneObject(std::string("mesh") + std::to_string(j));
+                    auto mesh = std::dynamic_pointer_cast<LineMesh>(object->getVisualGeometry());
+
+                    mesh->setVertexPositions(vertices);
+                    mesh->setLinesVertices(lines);
+                }
+            }
+
+            if (scene->getSceneObject("mesh" + std::to_string(numMeshes - 1)) && startupFrame == -1)
+            {
+                startupFrame = frame;
+                LOG(INFO) << "Start time: " << startWatch->getTimeElapsed();
+            }
+            if (frame == startupFrame + 100)
+            {
+                startFrame = frame;
+                watch->start();
+                watch->reset();
+                LOG(INFO) << "Starting time";
+            }
+            else if (frame == startFrame + 100 && startFrame != -1)
+            {
+                endTime = watch->getTimeElapsed();
+                LOG(INFO) << "Total time: " << endTime;
+                LOG(INFO) << "Frame time: " << endTime / (frame - startFrame);
+            }
+            frame++;
+            return true;
+        }
+    );
+
+    // Start simulation
+    startWatch->start();
+    startWatch->reset();
+    sdk->setActiveScene(scene);
+    sdk->startSimulation();
+}
diff --git a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.cpp b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.cpp
index e8fa3f8a2d39a3d04fa1d49bc2d01b982ee0d7f2..13705671eef01ee11588a4e313bb684fbb6e0548 100644
--- a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.cpp
+++ b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.cpp
@@ -23,7 +23,9 @@
 
 namespace imstk
 {
-VulkanLineMeshRenderDelegate::VulkanLineMeshRenderDelegate(std::shared_ptr<LineMesh> lineMesh, VulkanMemoryManager& memoryManager)
+VulkanLineMeshRenderDelegate::VulkanLineMeshRenderDelegate(std::shared_ptr<LineMesh> lineMesh,
+    SceneObject::Type type,
+    VulkanMemoryManager& memoryManager)
     : m_geometry(lineMesh)
 {
     m_numVertices = (uint32_t)m_geometry->getNumVertices();
@@ -38,17 +40,35 @@ VulkanLineMeshRenderDelegate::VulkanLineMeshRenderDelegate(std::shared_ptr<LineM
 
     m_geometry->getRenderMaterial()->m_isLineMesh = true;
 
-    this->initializeData(memoryManager, m_geometry->getRenderMaterial());
+    if (type == SceneObject::Type::FEMDeformable || type == SceneObject::Type::Pbd)
+    {
+        this->initializeData(memoryManager, m_geometry->getRenderMaterial(), VulkanVertexBufferMode::VERTEX_BUFFER_DYNAMIC);
 
-    this->updateVertexBuffer();
+        for (uint32_t i = 0; i < memoryManager.m_buffering; i++)
+        {
+            this->updateVertexBuffer(i);
+            this->update(i);
+        }
+    }
+    else
+    {
+        this->initializeData(memoryManager, m_geometry->getRenderMaterial(), VulkanVertexBufferMode::VERTEX_BUFFER_STATIC);
 
-    this->update(0);
+        this->updateVertexBuffer(0);
+        this->update(0);
+    }
 }
 
 void
-VulkanLineMeshRenderDelegate::updateVertexBuffer()
+VulkanLineMeshRenderDelegate::updateVertexBuffer(const uint32_t frameIndex)
 {
-    auto vertices = (VulkanBasicVertex *)m_vertexBuffer->getVertexMemory();
+    int frame = 0;
+    if (m_vertexBuffer->getMode() != VERTEX_BUFFER_STATIC)
+    {
+        frame = frameIndex;
+    }
+
+    auto vertices = (VulkanBasicVertex *)m_vertexBuffer->getVertexMemory(frame);
 
     auto colors = m_geometry->getVertexColors();
 
@@ -73,7 +93,7 @@ VulkanLineMeshRenderDelegate::updateVertexBuffer()
         }
     }
 
-    auto lines = (std::array<uint32_t, 2> *)m_vertexBuffer->getIndexMemory();
+    auto lines = (std::array<uint32_t, 2> *)m_vertexBuffer->getIndexMemory(frame);
 
     m_vertexBuffer->setNumIndices((uint32_t)m_geometry->getNumLines() * 2);
 
@@ -92,7 +112,7 @@ VulkanLineMeshRenderDelegate::update(const uint32_t frameIndex)
 
     if (m_geometry->m_dataModified)
     {
-        this->updateVertexBuffer();
+        this->updateVertexBuffer(frameIndex);
     }
 }
 
diff --git a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.h b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.h
index 35d9a556ac6f3a9b0436ba7af0a5b99194606444..da752f7bd2ef50150b851dcbee9c27ba714dd870 100644
--- a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.h
+++ b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.h
@@ -42,7 +42,9 @@ public:
     ///
     /// \brief Default constructor
     ///
-    VulkanLineMeshRenderDelegate(std::shared_ptr<LineMesh> LineMesh, VulkanMemoryManager& memoryManager);
+    VulkanLineMeshRenderDelegate(std::shared_ptr<LineMesh> LineMesh,
+        SceneObject::Type type,
+        VulkanMemoryManager& memoryManager);
 
     ///
     /// \brief Update render geometry
@@ -58,7 +60,7 @@ public:
     ///
     /// \brief Fill vertex buffer
     ///
-    void updateVertexBuffer();
+    void updateVertexBuffer(const uint32_t frameIndex);
 
 protected:
     std::shared_ptr<LineMesh> m_geometry;
diff --git a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp
index f897a4c540d815f58b90669fc32cbcfe0918af7e..ee9f73e2bf9104b5846bf8f626ec5e9f1a74600b 100644
--- a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp
+++ b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp
@@ -83,7 +83,7 @@ VulkanRenderDelegate::make_delegate(std::shared_ptr<Geometry> geom,
     case Geometry::Type::LineMesh:
     {
         auto lineMesh = std::dynamic_pointer_cast<LineMesh>(geom);
-        return std::make_shared<VulkanLineMeshRenderDelegate>(lineMesh, memoryManager);
+        return std::make_shared<VulkanLineMeshRenderDelegate>(lineMesh, type, memoryManager);
     }
     /*case Geometry::Type::HexahedralMesh:
     {
diff --git a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanSurfaceMeshRenderDelegate.cpp b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanSurfaceMeshRenderDelegate.cpp
index 6b11c218f25cb5dc91a664aa41336837ad62192b..73295c9a89f10f422d5e524c26afa818f179f8af 100644
--- a/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanSurfaceMeshRenderDelegate.cpp
+++ b/Source/Rendering/VulkanRenderer/RenderDelegate/imstkVulkanSurfaceMeshRenderDelegate.cpp
@@ -42,23 +42,32 @@ VulkanSurfaceMeshRenderDelegate::VulkanSurfaceMeshRenderDelegate(std::shared_ptr
     if (type == SceneObject::Type::FEMDeformable || type == SceneObject::Type::Pbd)
     {
         this->initializeData(memoryManager, m_geometry->getRenderMaterial(), VulkanVertexBufferMode::VERTEX_BUFFER_DYNAMIC);
+
+        for (uint32_t i = 0; i < memoryManager.m_buffering; i++)
+        {
+            this->updateVertexBuffer(i);
+            this->update(i);
+        }
     }
     else
     {
         this->initializeData(memoryManager, m_geometry->getRenderMaterial(), VulkanVertexBufferMode::VERTEX_BUFFER_STATIC);
-    }
 
-    for (uint32_t i = 0; i < memoryManager.m_buffering; i++)
-    {
-        this->updateVertexBuffer(i);
-        this->update(i);
+        this->updateVertexBuffer(0);
+        this->update(0);
     }
 }
 
 void
 VulkanSurfaceMeshRenderDelegate::updateVertexBuffer(uint32_t frameIndex)
 {
-    auto vertices = (VulkanBasicVertex *)m_vertexBuffer->getVertexMemory(frameIndex);
+    int frame = 0;
+    if (m_vertexBuffer->getMode() != VERTEX_BUFFER_STATIC)
+    {
+        frame = frameIndex;
+    }
+
+    auto vertices = (VulkanBasicVertex *)m_vertexBuffer->getVertexMemory(frame);
 
     auto normals = m_geometry->getVertexNormals();
     auto tangents = m_geometry->getVertexTangents();
@@ -89,23 +98,23 @@ VulkanSurfaceMeshRenderDelegate::updateVertexBuffer(uint32_t frameIndex)
                 normals[i][2]);
         }
 
-        if (tangents.size() == m_geometry->getNumVertices())
-        {
-            vertices[i].tangent = glm::vec3(
-                tangents[i][0],
-                tangents[i][1],
-                tangents[i][2]);
-        }
-
         if (UVs && UVs->size() == m_geometry->getNumVertices())
         {
+            if (tangents.size() == m_geometry->getNumVertices())
+            {
+                vertices[i].tangent = glm::vec3(
+                    tangents[i][0],
+                    tangents[i][1],
+                    tangents[i][2]);
+            }
+
             vertices[i].uv = glm::vec2(
                 (*UVs)[i][0],
                 (*UVs)[i][1]);
         }
     }
 
-    auto triangles = (std::array<uint32_t, 3> *)m_vertexBuffer->getIndexMemory(frameIndex);
+    auto triangles = (std::array<uint32_t, 3> *)m_vertexBuffer->getIndexMemory(frame);
 
     m_vertexBuffer->setNumIndices((uint32_t)m_geometry->getNumTriangles() * 3);
     for (unsigned i = 0; i < m_geometry->getNumTriangles(); i++)
diff --git a/Source/Rendering/VulkanRenderer/imstkVulkanMemoryManager.cpp b/Source/Rendering/VulkanRenderer/imstkVulkanMemoryManager.cpp
index dc029366dbe55571c08dc9cd2ae0be6c1a33e82d..3b003cd53865ab75ed41210acbc551fbf6a65707 100644
--- a/Source/Rendering/VulkanRenderer/imstkVulkanMemoryManager.cpp
+++ b/Source/Rendering/VulkanRenderer/imstkVulkanMemoryManager.cpp
@@ -115,7 +115,7 @@ VulkanMemoryManager::requestMemoryAllocation(
 
     if (vkAllocateMemory(m_device, &memoryInfo, nullptr, internalMemory->m_memory) != VK_SUCCESS)
     {
-        LOG(INFO) << "test";
+        LOG(INFO) << "Cannot allocate memory";
     }
 
     m_memoryAllocations[type].push_back(internalMemory);
diff --git a/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.cpp b/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.cpp
index b1615640b1f2dd238620b38629160abcebdb211e..814ddbd19cfcd18c872e9e289d578d63c35082b4 100644
--- a/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.cpp
+++ b/Source/Rendering/VulkanRenderer/imstkVulkanRenderer.cpp
@@ -687,6 +687,22 @@ VulkanRenderer::renderFrame()
         auto buffers = m_renderDelegates[renderDelegateIndex]->getBuffer().get();
         buffers->uploadBuffers(m_renderCommandBuffer[nextImageIndex]);
     }
+    VkMemoryBarrier barrier;
+    barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+    barrier.pNext = nullptr;
+    barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+    barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDEX_READ_BIT;
+
+    vkCmdPipelineBarrier(m_renderCommandBuffer[nextImageIndex],
+        VK_PIPELINE_STAGE_TRANSFER_BIT,
+        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+        0,
+        1,
+        &barrier,
+        0,
+        nullptr,
+        0,
+        nullptr);
 
     VkDeviceSize deviceSize = { 0 };
 
diff --git a/Source/Rendering/VulkanRenderer/imstkVulkanVertexBuffer.cpp b/Source/Rendering/VulkanRenderer/imstkVulkanVertexBuffer.cpp
index 66d1e018c63e9af37424179e37cec4a077e64a3b..afcc4bfe7a736d9f55074f5fb40fe17d12cd9261 100644
--- a/Source/Rendering/VulkanRenderer/imstkVulkanVertexBuffer.cpp
+++ b/Source/Rendering/VulkanRenderer/imstkVulkanVertexBuffer.cpp
@@ -56,7 +56,7 @@ VulkanVertexBuffer::VulkanVertexBuffer(VulkanMemoryManager& memoryManager,
                         vertexStagingBufferInfo,
                         VulkanMemoryType::STAGING_VERTEX);
 
-        if (m_mode = VERTEX_BUFFER_STATIC)
+        if (m_mode == VERTEX_BUFFER_STATIC)
         {
             m_vertexBuffer = memoryManager.requestBuffer(m_renderDevice,
                             vertexBufferInfo,
@@ -88,7 +88,7 @@ VulkanVertexBuffer::VulkanVertexBuffer(VulkanMemoryManager& memoryManager,
                         indexStagingBufferInfo,
                         VulkanMemoryType::STAGING_INDEX);
 
-        if (m_mode = VERTEX_BUFFER_STATIC)
+        if (m_mode == VERTEX_BUFFER_STATIC)
         {
             m_indexBuffer = memoryManager.requestBuffer(m_renderDevice,
                             indexBufferInfo,
@@ -153,7 +153,7 @@ VulkanVertexBuffer::updateVertexBuffer(std::vector<VulkanBasicVertex> * vertices
 void
 VulkanVertexBuffer::uploadBuffers(VkCommandBuffer& commandBuffer)
 {
-    if (m_mode == VERTEX_BUFFER_STATIC)
+    if (m_mode != VERTEX_BUFFER_STATIC)
     {
         return;
     }
@@ -233,4 +233,11 @@ VulkanVertexBuffer::bindBuffers(VkCommandBuffer * commandBuffer, uint32_t frameI
     vkCmdBindVertexBuffers(*commandBuffer, 0, 1, m_vertexBuffer->getBuffer(), &vertexOffset);
     vkCmdBindIndexBuffer(*commandBuffer, *m_indexBuffer->getBuffer(), indexOffset, VK_INDEX_TYPE_UINT32);
 }
+
+VulkanVertexBufferMode
+VulkanVertexBuffer::getMode()
+{
+    return m_mode;
+}
+
 }
\ No newline at end of file
diff --git a/Source/Rendering/VulkanRenderer/imstkVulkanVertexBuffer.h b/Source/Rendering/VulkanRenderer/imstkVulkanVertexBuffer.h
index d42d28ab14122785eed83347fd8289cb0742c148..020d7055fe4d172116c4ec6de6b4fd1f354d1fd0 100644
--- a/Source/Rendering/VulkanRenderer/imstkVulkanVertexBuffer.h
+++ b/Source/Rendering/VulkanRenderer/imstkVulkanVertexBuffer.h
@@ -77,6 +77,8 @@ public:
 
     void bindBuffers(VkCommandBuffer * commandBuffer, uint32_t frameIndex);
 
+    VulkanVertexBufferMode getMode();
+
 private:
     friend class VulkanRenderer;