Add setDirtyOffset for GEVulkanDynamicSPMBuffer

This commit is contained in:
Benau 2022-12-05 16:32:00 +08:00
parent 1d00e44f97
commit ddc0b9d1ed
6 changed files with 94 additions and 10 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -188,6 +188,7 @@ void Shadow::update(bool enabled)
.toIrrVector());
}
buffer->recalculateBoundingBox();
buffer->setDirtyOffset(0, irr::scene::EBT_VERTEX);
mesh->setBoundingBox(buffer->getBoundingBox());
}
} // update

View File

@ -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<uint16_t, 6> 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;

View File

@ -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)