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;