From ddc0b9d1ed8eb385faf6fc35c55dd8d742506d90 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 5 Dec 2022 16:32:00 +0800 Subject: [PATCH] Add setDirtyOffset for GEVulkanDynamicSPMBuffer --- .../include/ge_vulkan_dynamic_spm_buffer.hpp | 10 +++ .../src/ge_vulkan_dynamic_spm_buffer.cpp | 81 ++++++++++++++++--- lib/irrlicht/include/IMeshBuffer.h | 4 + src/graphics/shadow.cpp | 1 + src/graphics/skid_marks.cpp | 7 ++ src/items/rubber_band.cpp | 1 + 6 files changed, 94 insertions(+), 10 deletions(-) diff --git a/lib/graphics_engine/include/ge_vulkan_dynamic_spm_buffer.hpp b/lib/graphics_engine/include/ge_vulkan_dynamic_spm_buffer.hpp index c39a9ef32..1ebfc0494 100644 --- a/lib/graphics_engine/include/ge_vulkan_dynamic_spm_buffer.hpp +++ b/lib/graphics_engine/include/ge_vulkan_dynamic_spm_buffer.hpp @@ -5,6 +5,7 @@ namespace GE { +class GEVulkanDriver; class GEVulkanDynamicBuffer; class GEVulkanDynamicSPMBuffer : public GESPMBuffer @@ -13,6 +14,12 @@ private: GEVulkanDynamicBuffer* m_vertex_buffer; GEVulkanDynamicBuffer* m_index_buffer; + + GEVulkanDriver* m_vk; + + uint32_t* m_vertex_update_offsets; + + uint32_t* m_index_update_offsets; public: // ------------------------------------------------------------------------ GEVulkanDynamicSPMBuffer(); @@ -34,6 +41,9 @@ public: void updateVertexIndexBuffer(int buffer_index); // ------------------------------------------------------------------------ void drawDynamicVertexIndexBuffer(VkCommandBuffer cmd, int buffer_index); + // ------------------------------------------------------------------------ + void setDirtyOffset(irr::u32 offset, + irr::scene::E_BUFFER_TYPE buffer = irr::scene::EBT_VERTEX_AND_INDEX); }; } // end namespace GE diff --git a/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp b/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp index a4d2c0da4..829727eeb 100644 --- a/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp @@ -12,39 +12,69 @@ namespace GE // ---------------------------------------------------------------------------- GEVulkanDynamicSPMBuffer::GEVulkanDynamicSPMBuffer() { + unsigned frame_count = GEVulkanDriver::getMaxFrameInFlight() + 1; m_vertex_buffer = new GEVulkanDynamicBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 100, - GEVulkanDriver::getMaxFrameInFlight() + 1, 0); + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 100, frame_count, 0); m_index_buffer = new GEVulkanDynamicBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 100, - GEVulkanDriver::getMaxFrameInFlight() + 1, 0); - getVKDriver()->addDynamicSPMBuffer(this); + VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 100, frame_count, 0); + m_vk = getVKDriver(); + m_vk->addDynamicSPMBuffer(this); + m_vertex_update_offsets = new uint32_t[frame_count](); + m_index_update_offsets = new uint32_t[frame_count](); } // GEVulkanDynamicSPMBuffer // ---------------------------------------------------------------------------- GEVulkanDynamicSPMBuffer::~GEVulkanDynamicSPMBuffer() { - getVKDriver()->removeDynamicSPMBuffer(this); + m_vk->removeDynamicSPMBuffer(this); delete m_vertex_buffer; delete m_index_buffer; + delete [] m_vertex_update_offsets; + delete [] m_index_update_offsets; } // ~GEVulkanDynamicSPMBuffer // ---------------------------------------------------------------------------- void GEVulkanDynamicSPMBuffer::updateVertexIndexBuffer(int buffer_index) { + if (m_vertex_update_offsets[buffer_index] == m_vertices.size() && + m_index_update_offsets[buffer_index] == m_indices.size()) + return; + const size_t stride = sizeof(irr::video::S3DVertexSkinnedMesh) - 16; double vertex_size = (double)(m_vertices.size() * stride); double base = std::log2(vertex_size); - m_vertex_buffer->resizeIfNeeded(2 << (unsigned)base); + unsigned frame_count = GEVulkanDriver::getMaxFrameInFlight() + 1; + if (m_vertex_buffer->resizeIfNeeded(2 << (unsigned)base)) + std::fill_n(m_vertex_update_offsets, frame_count, 0); + uint8_t* mapped_addr = (uint8_t*)m_vertex_buffer->getMappedAddr() [buffer_index]; - for (unsigned i = 0; i < m_vertices.size(); i++) + unsigned voffset = m_vertex_update_offsets[buffer_index] * stride; + mapped_addr += voffset; + for (unsigned i = m_vertex_update_offsets[buffer_index]; + i < m_vertices.size(); i++) { memcpy(mapped_addr, &m_vertices[i], stride); mapped_addr += stride; } - m_index_buffer->setCurrentData(m_indices.data(), m_indices.size() * - sizeof(uint16_t), NULL, buffer_index); + m_vertex_update_offsets[buffer_index] = m_vertices.size(); + + double index_size = (double)(m_indices.size() * sizeof(uint16_t)); + base = std::log2(index_size); + if (m_index_buffer->resizeIfNeeded(2 << (unsigned)base)) + std::fill_n(m_index_update_offsets, frame_count, 0); + + mapped_addr = (uint8_t*)m_index_buffer->getMappedAddr() + [buffer_index]; + unsigned ioffset = m_index_update_offsets[buffer_index] * sizeof(uint16_t); + mapped_addr += ioffset; + for (unsigned i = m_index_update_offsets[buffer_index]; + i < m_indices.size(); i++) + { + memcpy(mapped_addr, &m_indices[i], sizeof(uint16_t)); + mapped_addr += sizeof(uint16_t); + } + m_index_update_offsets[buffer_index] = m_indices.size(); } // updateVertexIndexBuffer // ---------------------------------------------------------------------------- @@ -68,4 +98,35 @@ void GEVulkanDynamicSPMBuffer::drawDynamicVertexIndexBuffer(VkCommandBuffer cmd, vkCmdDrawIndexed(cmd, getIndexCount(), 1, 0, 0, 0); } // drawDynamicVertexIndexBuffer +// ---------------------------------------------------------------------------- +void GEVulkanDynamicSPMBuffer::setDirtyOffset(irr::u32 offset, + irr::scene::E_BUFFER_TYPE buffer) +{ + int vertex_update_offset = -1; + int index_update_offset = -1; + if (buffer == irr::scene::EBT_VERTEX_AND_INDEX) + vertex_update_offset = index_update_offset = offset; + else if (buffer == irr::scene::EBT_VERTEX) + vertex_update_offset = offset; + else if (buffer == irr::scene::EBT_INDEX) + index_update_offset = offset; + unsigned frame_count = GEVulkanDriver::getMaxFrameInFlight() + 1; + if (vertex_update_offset != -1) + { + for (unsigned i = 0; i < frame_count; i++) + { + if (m_vertex_update_offsets[i] > vertex_update_offset) + m_vertex_update_offsets[i] = vertex_update_offset; + } + } + if (index_update_offset != -1) + { + for (unsigned i = 0; i < frame_count; i++) + { + if (m_index_update_offsets[i] > index_update_offset) + m_index_update_offsets[i] = index_update_offset; + } + } +} // setDirtyOffset + } // end namespace GE diff --git a/lib/irrlicht/include/IMeshBuffer.h b/lib/irrlicht/include/IMeshBuffer.h index bc7dc567e..40d5073ea 100644 --- a/lib/irrlicht/include/IMeshBuffer.h +++ b/lib/irrlicht/include/IMeshBuffer.h @@ -146,6 +146,10 @@ namespace scene //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; + //! flags the meshbuffer as changed with offset, reloads hardware buffers + virtual void setDirtyOffset(u32 offset, + E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) {} + //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID_Vertex() const = 0; diff --git a/src/graphics/shadow.cpp b/src/graphics/shadow.cpp index 7ff7bc5de..5ccaf7aee 100644 --- a/src/graphics/shadow.cpp +++ b/src/graphics/shadow.cpp @@ -188,6 +188,7 @@ void Shadow::update(bool enabled) .toIrrVector()); } buffer->recalculateBoundingBox(); + buffer->setDirtyOffset(0, irr::scene::EBT_VERTEX); mesh->setBoundingBox(buffer->getBoundingBox()); } } // update diff --git a/src/graphics/skid_marks.cpp b/src/graphics/skid_marks.cpp index e8367590c..f7d45d669 100644 --- a/src/graphics/skid_marks.cpp +++ b/src/graphics/skid_marks.cpp @@ -372,6 +372,11 @@ void SkidMarks::SkidMarkQuads::addLegacy(const Vec3& left, v[1].m_all_uvs[0] = half_float_1; v[1].m_all_uvs[1] = half_distance; buffer->append(v.data(), v.size(), NULL, 0); + int vertex_update_offset = buffer->getVertexCount(); + vertex_update_offset -= 4; + if (vertex_update_offset < 0) + vertex_update_offset = 0; + buffer->setDirtyOffset(vertex_update_offset, irr::scene::EBT_VERTEX); } else { @@ -405,6 +410,8 @@ void SkidMarks::SkidMarkQuads::addLegacy(const Vec3& left, m_node->setVisible(true); std::array indices = {{ }}; buffer->append(NULL, 0, indices.data(), indices.size()); + buffer->setDirtyOffset(buffer->getIndexCount() - 6, + irr::scene::EBT_INDEX); unsigned idx = buffer->getIndexCount() - indices.size(); buffer->getIndices()[idx + 0] = n - 2; buffer->getIndices()[idx + 1] = n - 1; diff --git a/src/items/rubber_band.cpp b/src/items/rubber_band.cpp index 8b9252c86..3e137c736 100644 --- a/src/items/rubber_band.cpp +++ b/src/items/rubber_band.cpp @@ -203,6 +203,7 @@ void RubberBand::updateGraphics(float dt) buffer->getIndices()[5] = 3; } buffer->recalculateBoundingBox(); + buffer->setDirtyOffset(0, irr::scene::EBT_VERTEX_AND_INDEX); mesh->setBoundingBox(buffer->getBoundingBox()); } else if (m_dy_dc)