Use triple buffer to avoid memcpy after fence
This commit is contained in:
parent
982a5b2be8
commit
542ece64f9
@ -28,12 +28,11 @@
|
|||||||
namespace GE
|
namespace GE
|
||||||
{
|
{
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
ObjectData::ObjectData(irr::scene::ISceneNode* node, int material_id,
|
void ObjectData::init(irr::scene::ISceneNode* node, int material_id,
|
||||||
int skinning_offset, int irrlicht_material_id)
|
int skinning_offset, int irrlicht_material_id)
|
||||||
{
|
{
|
||||||
using namespace MiniGLM;
|
using namespace MiniGLM;
|
||||||
const irr::core::matrix4& model_mat = node->getAbsoluteTransformation();
|
const irr::core::matrix4& model_mat = node->getAbsoluteTransformation();
|
||||||
float translation[3] = { model_mat[12], model_mat[13], model_mat[14] };
|
|
||||||
irr::core::quaternion rotation(0.0f, 0.0f, 0.0f, 1.0f);
|
irr::core::quaternion rotation(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
irr::core::vector3df scale = model_mat.getScale();
|
irr::core::vector3df scale = model_mat.getScale();
|
||||||
if (scale.X != 0.0f && scale.Y != 0.0f && scale.Z != 0.0f)
|
if (scale.X != 0.0f && scale.Y != 0.0f && scale.Z != 0.0f)
|
||||||
@ -52,7 +51,8 @@ ObjectData::ObjectData(irr::scene::ISceneNode* node, int material_id,
|
|||||||
// Conjugated quaternion in glsl
|
// Conjugated quaternion in glsl
|
||||||
rotation.W = -rotation.W;
|
rotation.W = -rotation.W;
|
||||||
}
|
}
|
||||||
memcpy(&m_translation_x, translation, sizeof(translation));
|
memcpy(&m_translation_x, &node->getAbsoluteTransformation()[12],
|
||||||
|
sizeof(float) * 3);
|
||||||
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
|
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
|
||||||
memcpy(&m_scale_x, &scale, sizeof(irr::core::vector3df));
|
memcpy(&m_scale_x, &scale, sizeof(irr::core::vector3df));
|
||||||
m_skinning_offset = skinning_offset;
|
m_skinning_offset = skinning_offset;
|
||||||
@ -67,51 +67,50 @@ ObjectData::ObjectData(irr::scene::ISceneNode* node, int material_id,
|
|||||||
else
|
else
|
||||||
m_hue_change = 0.0f;
|
m_hue_change = 0.0f;
|
||||||
m_custom_vertex_color = irr::video::SColor((uint32_t)-1);
|
m_custom_vertex_color = irr::video::SColor((uint32_t)-1);
|
||||||
} // ObjectData
|
} // init
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
ObjectData::ObjectData(irr::scene::IBillboardSceneNode* node, int material_id,
|
void ObjectData::init(irr::scene::IBillboardSceneNode* node, int material_id,
|
||||||
const irr::core::quaternion& rotation)
|
const irr::core::quaternion& rotation)
|
||||||
{
|
{
|
||||||
const irr::core::matrix4& model_mat = node->getAbsoluteTransformation();
|
memcpy(&m_translation_x, &node->getAbsoluteTransformation()[12],
|
||||||
float translation[3] = { model_mat[12], model_mat[13], model_mat[14] };
|
sizeof(float) * 3);
|
||||||
irr::core::vector2df billboard_size = node->getSize();
|
|
||||||
irr::core::vector3df scale(billboard_size.X / 2.0f,
|
|
||||||
billboard_size.Y / 2.0f, 0);
|
|
||||||
memcpy(&m_translation_x, translation, sizeof(translation));
|
|
||||||
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
|
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
|
||||||
memcpy(&m_scale_x, &scale, sizeof(irr::core::vector3df));
|
irr::core::vector2df billboard_size = node->getSize();
|
||||||
|
m_scale_x = billboard_size.X / 2.0f;
|
||||||
|
m_scale_y = billboard_size.Y / 2.0f;
|
||||||
|
m_scale_z = 0.0f;
|
||||||
m_skinning_offset = 0;
|
m_skinning_offset = 0;
|
||||||
m_material_id = material_id;
|
m_material_id = material_id;
|
||||||
m_texture_trans[0] = 0.0f;
|
m_texture_trans[0] = 0.0f;
|
||||||
m_texture_trans[1] = 0.0f;
|
m_texture_trans[1] = 0.0f;
|
||||||
m_hue_change = 0.0f;
|
m_hue_change = 0.0f;
|
||||||
// Only support average of them at the moment
|
// Only support average of them at the moment
|
||||||
irr::video::SColor top, bottom;
|
irr::video::SColor top, bottom, output;
|
||||||
node->getColor(top, bottom);
|
node->getColor(top, bottom);
|
||||||
m_custom_vertex_color.setAlpha((top.getAlpha() + bottom.getAlpha()) / 2);
|
output.setAlpha((top.getAlpha() + bottom.getAlpha()) / 2);
|
||||||
m_custom_vertex_color.setRed((top.getRed() + bottom.getRed()) / 2);
|
output.setRed((top.getRed() + bottom.getRed()) / 2);
|
||||||
m_custom_vertex_color.setGreen((top.getGreen() + bottom.getGreen()) / 2);
|
output.setGreen((top.getGreen() + bottom.getGreen()) / 2);
|
||||||
m_custom_vertex_color.setBlue((top.getBlue() + bottom.getBlue()) / 2);
|
output.setBlue((top.getBlue() + bottom.getBlue()) / 2);
|
||||||
} // ObjectData
|
m_custom_vertex_color = output;
|
||||||
|
} // init
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
ObjectData::ObjectData(const irr::scene::SParticle& particle, int material_id,
|
void ObjectData::init(const irr::scene::SParticle& particle, int material_id,
|
||||||
const irr::core::quaternion& rotation)
|
const irr::core::quaternion& rotation)
|
||||||
{
|
{
|
||||||
using namespace MiniGLM;
|
|
||||||
memcpy(&m_translation_x, &particle.pos, sizeof(float) * 3);
|
memcpy(&m_translation_x, &particle.pos, sizeof(float) * 3);
|
||||||
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
|
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
|
||||||
irr::core::vector3df scale(particle.size.Width / 2.0f,
|
m_scale_x = particle.size.Width / 2.0f;
|
||||||
particle.size.Height / 2.0f, 0);
|
m_scale_y = particle.size.Height / 2.0f;
|
||||||
memcpy(&m_scale_x, &scale, sizeof(irr::core::vector3df));
|
m_scale_z = 0.0f;
|
||||||
m_skinning_offset = 0;
|
m_skinning_offset = 0;
|
||||||
m_material_id = material_id;
|
m_material_id = material_id;
|
||||||
m_texture_trans[0] = 0.0f;
|
m_texture_trans[0] = 0.0f;
|
||||||
m_texture_trans[1] = 0.0f;
|
m_texture_trans[1] = 0.0f;
|
||||||
m_hue_change = 0.0f;
|
m_hue_change = 0.0f;
|
||||||
m_custom_vertex_color = particle.color;
|
m_custom_vertex_color = particle.color;
|
||||||
} // ObjectData
|
} // init
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
GEVulkanDrawCall::GEVulkanDrawCall()
|
GEVulkanDrawCall::GEVulkanDrawCall()
|
||||||
@ -123,16 +122,7 @@ GEVulkanDrawCall::GEVulkanDrawCall()
|
|||||||
m_object_data_padded_size = 0;
|
m_object_data_padded_size = 0;
|
||||||
m_skinning_data_padded_size = 0;
|
m_skinning_data_padded_size = 0;
|
||||||
m_materials_padded_size = 0;
|
m_materials_padded_size = 0;
|
||||||
m_data_padding = NULL;
|
m_current_sbo_host_idx = 0;
|
||||||
const size_t ubo_padding = m_limits.minUniformBufferOffsetAlignment;
|
|
||||||
const size_t sbo_padding = m_limits.minStorageBufferOffsetAlignment;
|
|
||||||
size_t padding = std::max(
|
|
||||||
{
|
|
||||||
ubo_padding, sbo_padding, sizeof(irr::core::matrix4)
|
|
||||||
});
|
|
||||||
m_data_padding = new char[padding]();
|
|
||||||
irr::core::matrix4 identity;
|
|
||||||
memcpy(m_data_padding, identity.pointer(), sizeof(irr::core::matrix4));
|
|
||||||
m_data_layout = VK_NULL_HANDLE;
|
m_data_layout = VK_NULL_HANDLE;
|
||||||
m_descriptor_pool = VK_NULL_HANDLE;
|
m_descriptor_pool = VK_NULL_HANDLE;
|
||||||
m_pipeline_layout = VK_NULL_HANDLE;
|
m_pipeline_layout = VK_NULL_HANDLE;
|
||||||
@ -142,7 +132,6 @@ GEVulkanDrawCall::GEVulkanDrawCall()
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
GEVulkanDrawCall::~GEVulkanDrawCall()
|
GEVulkanDrawCall::~GEVulkanDrawCall()
|
||||||
{
|
{
|
||||||
delete [] m_data_padding;
|
|
||||||
delete m_culling_tool;
|
delete m_culling_tool;
|
||||||
delete m_dynamic_data;
|
delete m_dynamic_data;
|
||||||
delete m_sbo_data;
|
delete m_sbo_data;
|
||||||
@ -229,31 +218,6 @@ void GEVulkanDrawCall::generate()
|
|||||||
if (!m_visible_nodes.empty() && m_data_layout == VK_NULL_HANDLE)
|
if (!m_visible_nodes.empty() && m_data_layout == VK_NULL_HANDLE)
|
||||||
createVulkanData();
|
createVulkanData();
|
||||||
|
|
||||||
std::vector<std::pair<void*, size_t> > data_uploading;
|
|
||||||
std::unordered_map<irr::scene::ISceneNode*, int> skinning_offets;
|
|
||||||
int added_joint = 1;
|
|
||||||
m_skinning_data_padded_size = sizeof(irr::core::matrix4);
|
|
||||||
data_uploading.emplace_back((void*)m_data_padding,
|
|
||||||
sizeof(irr::core::matrix4));
|
|
||||||
for (GEVulkanAnimatedMeshSceneNode* node : m_skinning_nodes)
|
|
||||||
{
|
|
||||||
int bone_count = node->getSPM()->getJointCount();
|
|
||||||
size_t bone_size = sizeof(irr::core::matrix4) * bone_count;
|
|
||||||
data_uploading.emplace_back(
|
|
||||||
(void*)node->getSkinningMatrices().data(), bone_size);
|
|
||||||
skinning_offets[node] = added_joint;
|
|
||||||
added_joint += bone_count;
|
|
||||||
m_skinning_data_padded_size += bone_size;
|
|
||||||
}
|
|
||||||
size_t sbo_alignment = m_limits.minStorageBufferOffsetAlignment;
|
|
||||||
size_t padding = getPadding(m_skinning_data_padded_size, sbo_alignment);
|
|
||||||
if (padding > 0)
|
|
||||||
{
|
|
||||||
m_skinning_data_padded_size += padding;
|
|
||||||
data_uploading.emplace_back((void*)m_data_padding,
|
|
||||||
padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
using Nodes = std::pair<GESPMBuffer*, std::unordered_map<
|
using Nodes = std::pair<GESPMBuffer*, std::unordered_map<
|
||||||
std::string, std::vector<std::pair<irr::scene::ISceneNode*, int
|
std::string, std::vector<std::pair<irr::scene::ISceneNode*, int
|
||||||
> > > >;
|
> > > >;
|
||||||
@ -288,6 +252,56 @@ void GEVulkanDrawCall::generate()
|
|||||||
return nodes_area.at(a.first) < nodes_area.at(b.first) ;
|
return nodes_area.at(a.first) < nodes_area.at(b.first) ;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
size_t min_size = 0;
|
||||||
|
start:
|
||||||
|
m_cmds.clear();
|
||||||
|
m_materials.clear();
|
||||||
|
m_materials_data.clear();
|
||||||
|
|
||||||
|
m_sbo_data->resizeIfNeeded(min_size);
|
||||||
|
uint8_t* mapped_addr = (uint8_t*)m_sbo_data->getMappedAddr()
|
||||||
|
[m_current_sbo_host_idx];
|
||||||
|
|
||||||
|
std::unordered_map<irr::scene::ISceneNode*, int> skinning_offets;
|
||||||
|
int added_joint = 1;
|
||||||
|
m_skinning_data_padded_size = sizeof(irr::core::matrix4);
|
||||||
|
|
||||||
|
static irr::core::matrix4 identity = irr::core::matrix4();
|
||||||
|
memcpy(mapped_addr, identity.pointer(), sizeof(irr::core::matrix4));
|
||||||
|
size_t written_size = sizeof(irr::core::matrix4);
|
||||||
|
mapped_addr += sizeof(irr::core::matrix4);
|
||||||
|
|
||||||
|
for (GEVulkanAnimatedMeshSceneNode* node : m_skinning_nodes)
|
||||||
|
{
|
||||||
|
int bone_count = node->getSPM()->getJointCount();
|
||||||
|
size_t bone_size = sizeof(irr::core::matrix4) * bone_count;
|
||||||
|
if (written_size + bone_size > m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size = (written_size + bone_size) * 2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
memcpy(mapped_addr, node->getSkinningMatrices().data(), bone_size);
|
||||||
|
written_size += bone_size;
|
||||||
|
mapped_addr += bone_size;
|
||||||
|
skinning_offets[node] = added_joint;
|
||||||
|
added_joint += bone_count;
|
||||||
|
m_skinning_data_padded_size += bone_size;
|
||||||
|
}
|
||||||
|
size_t sbo_alignment = m_limits.minStorageBufferOffsetAlignment;
|
||||||
|
size_t skinning_padding = getPadding(m_skinning_data_padded_size,
|
||||||
|
sbo_alignment);
|
||||||
|
if (skinning_padding > 0)
|
||||||
|
{
|
||||||
|
if (written_size + skinning_padding > m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size = (written_size + skinning_padding) * 2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
m_skinning_data_padded_size += skinning_padding;
|
||||||
|
written_size += skinning_padding;
|
||||||
|
mapped_addr += skinning_padding;
|
||||||
|
}
|
||||||
|
|
||||||
const bool use_base_vertex = GEVulkanFeatures::supportsBaseVertexRendering();
|
const bool use_base_vertex = GEVulkanFeatures::supportsBaseVertexRendering();
|
||||||
const bool bind_mesh_textures =
|
const bool bind_mesh_textures =
|
||||||
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
|
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
|
||||||
@ -302,6 +316,9 @@ void GEVulkanDrawCall::generate()
|
|||||||
};
|
};
|
||||||
std::unordered_map<irr::scene::IMesh*, std::vector<InstanceKey> >
|
std::unordered_map<irr::scene::IMesh*, std::vector<InstanceKey> >
|
||||||
instance_keys;
|
instance_keys;
|
||||||
|
size_t instance_offset = 0;
|
||||||
|
const uint8_t* instance_start_ptr = mapped_addr;
|
||||||
|
std::unordered_map<uint32_t, uint32_t> offset_map;
|
||||||
for (auto& p : visible_nodes)
|
for (auto& p : visible_nodes)
|
||||||
{
|
{
|
||||||
TexturesList textures = getTexturesList(p.first->getMaterial());
|
TexturesList textures = getTexturesList(p.first->getMaterial());
|
||||||
@ -377,9 +394,18 @@ void GEVulkanDrawCall::generate()
|
|||||||
}
|
}
|
||||||
if (r.second == BILLBOARD_NODE)
|
if (r.second == BILLBOARD_NODE)
|
||||||
{
|
{
|
||||||
m_visible_objects.emplace_back(
|
if (written_size + sizeof(ObjectData) >
|
||||||
|
m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size = (written_size + sizeof(ObjectData)) * 2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
ObjectData* obj = (ObjectData*)mapped_addr;
|
||||||
|
obj->init(
|
||||||
static_cast<irr::scene::IBillboardSceneNode*>(
|
static_cast<irr::scene::IBillboardSceneNode*>(
|
||||||
node), material_id, m_billboard_rotation);
|
node), material_id, m_billboard_rotation);
|
||||||
|
written_size += sizeof(ObjectData);
|
||||||
|
mapped_addr += sizeof(ObjectData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -395,10 +421,20 @@ void GEVulkanDrawCall::generate()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
visible_count += ps - 1;
|
visible_count += ps - 1;
|
||||||
|
if (written_size + sizeof(ObjectData) * ps >
|
||||||
|
m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size =
|
||||||
|
(written_size + sizeof(ObjectData) * ps) * 2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
ObjectData* obj = (ObjectData*)mapped_addr;
|
||||||
for (unsigned i = 0; i < ps; i++)
|
for (unsigned i = 0; i < ps; i++)
|
||||||
{
|
{
|
||||||
m_visible_objects.emplace_back(particles[i],
|
obj[i].init(particles[i], material_id,
|
||||||
material_id, m_billboard_rotation);
|
m_billboard_rotation);
|
||||||
|
written_size += sizeof(ObjectData);
|
||||||
|
mapped_addr += sizeof(ObjectData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -408,9 +444,17 @@ void GEVulkanDrawCall::generate()
|
|||||||
auto it = skinning_offets.find(node);
|
auto it = skinning_offets.find(node);
|
||||||
if (it != skinning_offets.end())
|
if (it != skinning_offets.end())
|
||||||
skinning_offset = it->second;
|
skinning_offset = it->second;
|
||||||
m_visible_objects.emplace_back(node,
|
if (written_size + sizeof(ObjectData) >
|
||||||
bind_mesh_textures ? -1 : material_id, skinning_offset,
|
m_sbo_data->getSize())
|
||||||
r.second);
|
{
|
||||||
|
min_size = (written_size + sizeof(ObjectData)) * 2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
ObjectData* obj = (ObjectData*)mapped_addr;
|
||||||
|
obj->init(node, bind_mesh_textures ? -1 : material_id,
|
||||||
|
skinning_offset, r.second);
|
||||||
|
written_size += sizeof(ObjectData);
|
||||||
|
mapped_addr += sizeof(ObjectData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VkDrawIndexedIndirectCommand cmd;
|
VkDrawIndexedIndirectCommand cmd;
|
||||||
@ -421,6 +465,24 @@ void GEVulkanDrawCall::generate()
|
|||||||
if (skip_instance_key || it == cur_key.end())
|
if (skip_instance_key || it == cur_key.end())
|
||||||
{
|
{
|
||||||
cmd.firstInstance = accumulated_instance;
|
cmd.firstInstance = accumulated_instance;
|
||||||
|
if (!use_base_vertex)
|
||||||
|
{
|
||||||
|
offset_map[accumulated_instance] = instance_offset;
|
||||||
|
size_t instance_padding = getPadding(written_size,
|
||||||
|
sbo_alignment);
|
||||||
|
if (instance_padding > 0)
|
||||||
|
{
|
||||||
|
if (written_size + instance_padding >
|
||||||
|
m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size = (written_size + instance_padding) * 2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
written_size += instance_padding;
|
||||||
|
mapped_addr += instance_padding;
|
||||||
|
}
|
||||||
|
instance_offset = mapped_addr - instance_start_ptr;
|
||||||
|
}
|
||||||
accumulated_instance += visible_count;
|
accumulated_instance += visible_count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -430,7 +492,7 @@ void GEVulkanDrawCall::generate()
|
|||||||
std::string sorting_key =
|
std::string sorting_key =
|
||||||
std::string(1, settings.m_drawing_priority) + cur_shader;
|
std::string(1, settings.m_drawing_priority) + cur_shader;
|
||||||
m_cmds.push_back({ cmd, cur_shader, sorting_key, p.first,
|
m_cmds.push_back({ cmd, cur_shader, sorting_key, p.first,
|
||||||
settings.isTransparent() });
|
settings.isTransparent(), offset_map[cmd.firstInstance] });
|
||||||
if (!skip_instance_key && it == cur_key.end())
|
if (!skip_instance_key && it == cur_key.end())
|
||||||
cur_key.push_back(key);
|
cur_key.push_back(key);
|
||||||
}
|
}
|
||||||
@ -456,45 +518,18 @@ void GEVulkanDrawCall::generate()
|
|||||||
return !a.m_transparent;
|
return !a.m_transparent;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (use_base_vertex)
|
m_object_data_padded_size = written_size - m_skinning_data_padded_size;
|
||||||
|
size_t object_padding = getPadding(written_size, sbo_alignment);
|
||||||
|
if (object_padding > 0)
|
||||||
{
|
{
|
||||||
const size_t object_data_size =
|
if (written_size + object_padding > m_sbo_data->getSize())
|
||||||
sizeof(ObjectData) * m_visible_objects.size();
|
|
||||||
data_uploading.emplace_back((void*)m_visible_objects.data(),
|
|
||||||
object_data_size);
|
|
||||||
m_object_data_padded_size = object_data_size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_object_data_padded_size = 0;
|
|
||||||
std::unordered_map<uint32_t, size_t> offset_map;
|
|
||||||
for (unsigned i = 0; i < m_cmds.size(); i++)
|
|
||||||
{
|
{
|
||||||
auto& cmd = m_cmds[i];
|
min_size = (written_size + object_padding) * 2;
|
||||||
uint32_t first_instance = cmd.m_cmd.firstInstance;
|
goto start;
|
||||||
if (offset_map.find(first_instance) == offset_map.end())
|
|
||||||
{
|
|
||||||
size_t instance_size =
|
|
||||||
cmd.m_cmd.instanceCount * sizeof(ObjectData);
|
|
||||||
data_uploading.emplace_back(
|
|
||||||
&m_visible_objects[first_instance], instance_size);
|
|
||||||
size_t cur_padding = getPadding(m_object_data_padded_size +
|
|
||||||
instance_size, sbo_alignment);
|
|
||||||
if (cur_padding > 0)
|
|
||||||
{
|
|
||||||
instance_size += cur_padding;
|
|
||||||
data_uploading.emplace_back((void*)m_data_padding,
|
|
||||||
cur_padding);
|
|
||||||
}
|
|
||||||
m_sbo_data_offset.push_back(m_object_data_padded_size);
|
|
||||||
offset_map[cmd.m_cmd.firstInstance] = m_object_data_padded_size;
|
|
||||||
m_object_data_padded_size += instance_size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_sbo_data_offset.push_back(offset_map.at(first_instance));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
m_object_data_padded_size += object_padding;
|
||||||
|
written_size += object_padding;
|
||||||
|
mapped_addr += object_padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_materials_padded_size = 0;
|
m_materials_padded_size = 0;
|
||||||
@ -508,15 +543,25 @@ void GEVulkanDrawCall::generate()
|
|||||||
if (cmd.m_shader != cur_shader)
|
if (cmd.m_shader != cur_shader)
|
||||||
{
|
{
|
||||||
size_t material_size = material.second.size() * sizeof(int);
|
size_t material_size = material.second.size() * sizeof(int);
|
||||||
m_data_uploading.emplace_back(
|
if (written_size + material_size > m_sbo_data->getSize())
|
||||||
material.second.data(), material_size);
|
{
|
||||||
size_t cur_padding = getPadding(m_materials_padded_size +
|
min_size = (written_size + material_size) * 2;
|
||||||
material_size, sbo_alignment);
|
goto start;
|
||||||
|
}
|
||||||
|
memcpy(mapped_addr, material.second.data(), material_size);
|
||||||
|
written_size += material_size;
|
||||||
|
mapped_addr += material_size;
|
||||||
|
size_t cur_padding = getPadding(written_size, sbo_alignment);
|
||||||
if (cur_padding > 0)
|
if (cur_padding > 0)
|
||||||
{
|
{
|
||||||
|
if (written_size + cur_padding > m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size = (written_size + cur_padding) * 2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
written_size += cur_padding;
|
||||||
|
mapped_addr += cur_padding;
|
||||||
material_size += cur_padding;
|
material_size += cur_padding;
|
||||||
m_data_uploading.emplace_back((void*)m_data_padding,
|
|
||||||
cur_padding);
|
|
||||||
}
|
}
|
||||||
material.first = m_materials_padded_size;
|
material.first = m_materials_padded_size;
|
||||||
m_materials_padded_size += material_size;
|
m_materials_padded_size += material_size;
|
||||||
@ -528,23 +573,47 @@ void GEVulkanDrawCall::generate()
|
|||||||
|
|
||||||
auto& material = m_materials_data[m_cmds.back().m_shader];
|
auto& material = m_materials_data[m_cmds.back().m_shader];
|
||||||
size_t material_size = material.second.size() * sizeof(int);
|
size_t material_size = material.second.size() * sizeof(int);
|
||||||
m_data_uploading.emplace_back(
|
if (written_size + material_size > m_sbo_data->getSize())
|
||||||
material.second.data(), material_size);
|
{
|
||||||
size_t cur_padding = getPadding(m_materials_padded_size +
|
min_size = (written_size + material_size) * 2;
|
||||||
material_size, sbo_alignment);
|
goto start;
|
||||||
|
}
|
||||||
|
memcpy(mapped_addr, material.second.data(), material_size);
|
||||||
|
written_size += material_size;
|
||||||
|
mapped_addr += material_size;
|
||||||
|
size_t cur_padding = getPadding(written_size, sbo_alignment);
|
||||||
if (cur_padding > 0)
|
if (cur_padding > 0)
|
||||||
{
|
{
|
||||||
|
if (written_size + cur_padding > m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size = (written_size + cur_padding) * 2;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
written_size += cur_padding;
|
||||||
|
mapped_addr += cur_padding;
|
||||||
material_size += cur_padding;
|
material_size += cur_padding;
|
||||||
m_data_uploading.emplace_back((void*)m_data_padding,
|
|
||||||
cur_padding);
|
|
||||||
}
|
}
|
||||||
material.first = m_materials_padded_size;
|
material.first = m_materials_padded_size;
|
||||||
m_materials_padded_size += material_size;
|
m_materials_padded_size += material_size;
|
||||||
m_data_uploading.insert(m_data_uploading.end(), data_uploading.begin(),
|
|
||||||
data_uploading.end());
|
// Make sure dynamic offsets of materials won't become invalid
|
||||||
|
if (written_size + m_materials_padded_size > m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size = written_size + m_materials_padded_size;
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!use_base_vertex)
|
||||||
|
{
|
||||||
|
// Make sure dynamic offset of objects won't become invalid
|
||||||
|
if (m_skinning_data_padded_size + (m_object_data_padded_size * 2) >
|
||||||
|
m_sbo_data->getSize())
|
||||||
|
{
|
||||||
|
min_size = m_skinning_data_padded_size +
|
||||||
|
(m_object_data_padded_size * 2);
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
std::swap(m_data_uploading, data_uploading);
|
|
||||||
} // generate
|
} // generate
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -1036,7 +1105,7 @@ void GEVulkanDrawCall::createVulkanData()
|
|||||||
// Using VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
// Using VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
||||||
// will be a lot slower when there are many objects (like particles)
|
// will be a lot slower when there are many objects (like particles)
|
||||||
m_sbo_data = new GEVulkanDynamicBuffer(flags, getInitialSBOSize(),
|
m_sbo_data = new GEVulkanDynamicBuffer(flags, getInitialSBOSize(),
|
||||||
GEVulkanDriver::getMaxFrameInFlight(), 0,
|
GEVulkanDriver::getMaxFrameInFlight() + 1, 0,
|
||||||
false/*enable_host_transfer*/);
|
false/*enable_host_transfer*/);
|
||||||
} // createVulkanData
|
} // createVulkanData
|
||||||
|
|
||||||
@ -1073,31 +1142,24 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk,
|
|||||||
}
|
}
|
||||||
m_dynamic_data->setCurrentData(data_uploading, cmd);
|
m_dynamic_data->setCurrentData(data_uploading, cmd);
|
||||||
|
|
||||||
const bool use_base_vertex = GEVulkanFeatures::supportsBaseVertexRendering();
|
const size_t whole_size = m_skinning_data_padded_size +
|
||||||
size_t min_size = 0;
|
m_object_data_padded_size + m_materials_padded_size;
|
||||||
if (!use_base_vertex)
|
vmaFlushAllocation(vk->getVmaAllocator(),
|
||||||
{
|
m_sbo_data->getHostMemory()[m_current_sbo_host_idx], 0,
|
||||||
// Make sure dynamic offset won't become invaild
|
whole_size);
|
||||||
min_size = m_skinning_data_padded_size +
|
|
||||||
(m_object_data_padded_size * 2);
|
|
||||||
}
|
|
||||||
else if (use_multidraw)
|
|
||||||
{
|
|
||||||
min_size = (m_materials_padded_size * 2) +
|
|
||||||
m_skinning_data_padded_size + m_object_data_padded_size;
|
|
||||||
}
|
|
||||||
m_sbo_data->resizeIfNeeded(min_size);
|
|
||||||
m_sbo_data->setCurrentData(m_data_uploading, cmd);
|
|
||||||
|
|
||||||
VkMemoryBarrier barrier = {};
|
if (!GEVulkanDynamicBuffer::supportsHostTransfer())
|
||||||
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
{
|
||||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
VkMemoryBarrier barrier = {};
|
||||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
||||||
if (use_multidraw)
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
barrier.dstAccessMask |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
if (use_multidraw)
|
||||||
|
barrier.dstAccessMask |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
|
||||||
|
|
||||||
vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage, 0, 1,
|
vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage, 0,
|
||||||
&barrier, 0, NULL, 0, NULL);
|
1, &barrier, 0, NULL, 0, NULL);
|
||||||
|
}
|
||||||
} // uploadDynamicData
|
} // uploadDynamicData
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -1132,9 +1194,9 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
|
|||||||
data_set[0].pBufferInfo = &ubo_info;
|
data_set[0].pBufferInfo = &ubo_info;
|
||||||
|
|
||||||
VkDescriptorBufferInfo sbo_info_objects;
|
VkDescriptorBufferInfo sbo_info_objects;
|
||||||
sbo_info_objects.buffer = m_sbo_data->getCurrentBuffer();
|
sbo_info_objects.buffer =
|
||||||
sbo_info_objects.offset =
|
m_sbo_data->getHostBuffer()[m_current_sbo_host_idx];
|
||||||
m_materials_padded_size + m_skinning_data_padded_size;
|
sbo_info_objects.offset = m_skinning_data_padded_size;
|
||||||
sbo_info_objects.range = m_object_data_padded_size;
|
sbo_info_objects.range = m_object_data_padded_size;
|
||||||
|
|
||||||
data_set[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
data_set[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
@ -1148,8 +1210,9 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
|
|||||||
data_set[1].pBufferInfo = &sbo_info_objects;
|
data_set[1].pBufferInfo = &sbo_info_objects;
|
||||||
|
|
||||||
VkDescriptorBufferInfo sbo_info_skinning;
|
VkDescriptorBufferInfo sbo_info_skinning;
|
||||||
sbo_info_skinning.buffer = m_sbo_data->getCurrentBuffer();
|
sbo_info_skinning.buffer =
|
||||||
sbo_info_skinning.offset = m_materials_padded_size;
|
m_sbo_data->getHostBuffer()[m_current_sbo_host_idx];
|
||||||
|
sbo_info_skinning.offset = 0;
|
||||||
sbo_info_skinning.range = m_skinning_data_padded_size;
|
sbo_info_skinning.range = m_skinning_data_padded_size;
|
||||||
|
|
||||||
data_set[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
data_set[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
@ -1163,8 +1226,10 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
|
|||||||
data_set[2].pBufferInfo = &sbo_info_skinning;
|
data_set[2].pBufferInfo = &sbo_info_skinning;
|
||||||
|
|
||||||
VkDescriptorBufferInfo sbo_info_material;
|
VkDescriptorBufferInfo sbo_info_material;
|
||||||
sbo_info_material.buffer = m_sbo_data->getCurrentBuffer();
|
sbo_info_material.buffer =
|
||||||
sbo_info_material.offset = 0;
|
m_sbo_data->getHostBuffer()[m_current_sbo_host_idx];
|
||||||
|
sbo_info_material.offset = m_skinning_data_padded_size +
|
||||||
|
m_object_data_padded_size;
|
||||||
sbo_info_material.range = m_materials_padded_size;
|
sbo_info_material.range = m_materials_padded_size;
|
||||||
if (bind_mesh_textures)
|
if (bind_mesh_textures)
|
||||||
{
|
{
|
||||||
@ -1332,7 +1397,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
|
|||||||
std::array<uint32_t, 3> dynamic_offsets =
|
std::array<uint32_t, 3> dynamic_offsets =
|
||||||
{{
|
{{
|
||||||
0u,
|
0u,
|
||||||
uint32_t(m_sbo_data_offset[i]),
|
m_cmds[i].m_dynamic_offset,
|
||||||
0u
|
0u
|
||||||
}};
|
}};
|
||||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
@ -1347,6 +1412,9 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
|
|||||||
}
|
}
|
||||||
if (!drawn_skybox)
|
if (!drawn_skybox)
|
||||||
GEVulkanSkyBoxRenderer::render(cmd, cam);
|
GEVulkanSkyBoxRenderer::render(cmd, cam);
|
||||||
|
|
||||||
|
m_current_sbo_host_idx = (m_current_sbo_host_idx + 1) %
|
||||||
|
(GEVulkanDriver::getMaxFrameInFlight() + 1);
|
||||||
} // render
|
} // render
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -51,14 +51,14 @@ struct ObjectData
|
|||||||
int m_material_id;
|
int m_material_id;
|
||||||
float m_texture_trans[2];
|
float m_texture_trans[2];
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
ObjectData(irr::scene::ISceneNode* node, int material_id,
|
void init(irr::scene::ISceneNode* node, int material_id,
|
||||||
int skinning_offset, int irrlicht_material_id);
|
int skinning_offset, int irrlicht_material_id);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
ObjectData(irr::scene::IBillboardSceneNode* node, int material_id,
|
void init(irr::scene::IBillboardSceneNode* node, int material_id,
|
||||||
const irr::core::quaternion& rotation);
|
const irr::core::quaternion& rotation);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
ObjectData(const irr::scene::SParticle& particle, int material_id,
|
void init(const irr::scene::SParticle& particle, int material_id,
|
||||||
const irr::core::quaternion& rotation);
|
const irr::core::quaternion& rotation);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineSettings
|
struct PipelineSettings
|
||||||
@ -85,6 +85,7 @@ struct DrawCallData
|
|||||||
std::string m_sorting_key;
|
std::string m_sorting_key;
|
||||||
GESPMBuffer* m_mb;
|
GESPMBuffer* m_mb;
|
||||||
bool m_transparent;
|
bool m_transparent;
|
||||||
|
uint32_t m_dynamic_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GEVulkanDrawCall
|
class GEVulkanDrawCall
|
||||||
@ -125,7 +126,7 @@ private:
|
|||||||
|
|
||||||
size_t m_materials_padded_size;
|
size_t m_materials_padded_size;
|
||||||
|
|
||||||
char* m_data_padding;
|
int m_current_sbo_host_idx;
|
||||||
|
|
||||||
VkDescriptorSetLayout m_data_layout;
|
VkDescriptorSetLayout m_data_layout;
|
||||||
|
|
||||||
@ -144,10 +145,6 @@ private:
|
|||||||
|
|
||||||
std::unordered_set<GEVulkanAnimatedMeshSceneNode*> m_skinning_nodes;
|
std::unordered_set<GEVulkanAnimatedMeshSceneNode*> m_skinning_nodes;
|
||||||
|
|
||||||
std::vector<std::pair<void*, size_t> > m_data_uploading;
|
|
||||||
|
|
||||||
std::vector<size_t> m_sbo_data_offset;
|
|
||||||
|
|
||||||
std::unordered_map<std::string, std::pair<uint32_t, std::vector<int> > >
|
std::unordered_map<std::string, std::pair<uint32_t, std::vector<int> > >
|
||||||
m_materials_data;
|
m_materials_data;
|
||||||
|
|
||||||
@ -220,8 +217,6 @@ public:
|
|||||||
m_visible_objects.clear();
|
m_visible_objects.clear();
|
||||||
m_materials.clear();
|
m_materials.clear();
|
||||||
m_skinning_nodes.clear();
|
m_skinning_nodes.clear();
|
||||||
m_data_uploading.clear();
|
|
||||||
m_sbo_data_offset.clear();
|
|
||||||
m_materials_data.clear();
|
m_materials_data.clear();
|
||||||
}
|
}
|
||||||
}; // GEVulkanDrawCall
|
}; // GEVulkanDrawCall
|
||||||
|
@ -52,6 +52,8 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void resizeIfNeeded(size_t new_size);
|
void resizeIfNeeded(size_t new_size);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
size_t getSize() const { return m_size; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
size_t getRealSize() const { return m_real_size; }
|
size_t getRealSize() const { return m_real_size; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
std::vector<VkBuffer>& getHostBuffer() { return m_host_buffer; }
|
std::vector<VkBuffer>& getHostBuffer() { return m_host_buffer; }
|
||||||
|
Loading…
Reference in New Issue
Block a user