Add rendering for GEVulkanDynamicSPMBuffer

This commit is contained in:
Benau 2022-12-01 16:16:58 +08:00
parent 392bdbf78b
commit 1d00e44f97
6 changed files with 269 additions and 79 deletions

View File

@ -15,6 +15,7 @@
#include <array>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <vector>
@ -26,6 +27,7 @@ namespace GE
class GESPM;
class GEVulkanDepthTexture;
class GEVulkanDrawCall;
class GEVulkanDynamicSPMBuffer;
class GEVulkanFBOTexture;
class GEVulkanMeshCache;
class GEVulkanTextureDescriptor;
@ -366,6 +368,10 @@ namespace GE
std::unique_ptr<GEVulkanDrawCall> getDrawCallFromCache();
GESPM* getBillboardQuad() const { return m_billboard_quad; }
int getCurrentBufferIdx() const { return m_current_buffer_idx; }
void addDynamicSPMBuffer(GEVulkanDynamicSPMBuffer* buffer)
{ m_dynamic_spm_buffers.insert(buffer); }
void removeDynamicSPMBuffer(GEVulkanDynamicSPMBuffer* buffer)
{ m_dynamic_spm_buffers.erase(buffer); }
private:
struct SwapChainSupportDetails
{
@ -511,6 +517,7 @@ namespace GE
std::vector<std::unique_ptr<GEVulkanDrawCall> > m_draw_calls_cache;
GESPM* m_billboard_quad;
int m_current_buffer_idx;
std::set<GEVulkanDynamicSPMBuffer*> m_dynamic_spm_buffers;
void createInstance(SDL_Window* window);
void findPhysicalDevice();

View File

@ -30,6 +30,10 @@ public:
virtual void createVertexIndexBuffer() {}
// ------------------------------------------------------------------------
virtual void destroyVertexIndexBuffer() {}
// ------------------------------------------------------------------------
void updateVertexIndexBuffer(int buffer_index);
// ------------------------------------------------------------------------
void drawDynamicVertexIndexBuffer(VkCommandBuffer cmd, int buffer_index);
};
} // end namespace GE

View File

@ -4,12 +4,12 @@
#include "ge_main.hpp"
#include "ge_render_info.hpp"
#include "ge_spm.hpp"
#include "ge_spm_buffer.hpp"
#include "ge_vulkan_animated_mesh_scene_node.hpp"
#include "ge_vulkan_billboard_buffer.hpp"
#include "ge_vulkan_camera_scene_node.hpp"
#include "ge_vulkan_driver.hpp"
#include "ge_vulkan_dynamic_buffer.hpp"
#include "ge_vulkan_dynamic_spm_buffer.hpp"
#include "ge_vulkan_fbo_texture.hpp"
#include "ge_vulkan_features.hpp"
#include "ge_vulkan_mesh_cache.hpp"
@ -188,6 +188,7 @@ GEVulkanDrawCall::GEVulkanDrawCall()
m_object_data_padded_size = 0;
m_skinning_data_padded_size = 0;
m_materials_padded_size = 0;
m_dynamic_spm_padded_size = 0;
m_update_data_descriptor_sets = true;
m_data_layout = VK_NULL_HANDLE;
m_descriptor_pool = VK_NULL_HANDLE;
@ -247,7 +248,12 @@ void GEVulkanDrawCall::addNode(irr::scene::ISceneNode* node)
const std::string& shader = getShader(node, i);
if (buffer->getHardwareMappingHint_Vertex() == irr::scene::EHM_STREAM ||
buffer->getHardwareMappingHint_Index() == irr::scene::EHM_STREAM)
{
GEVulkanDynamicSPMBuffer* dbuffer = static_cast<
GEVulkanDynamicSPMBuffer*>(buffer);
m_dynamic_spm_buffers[shader].emplace_back(dbuffer, node);
continue;
}
m_visible_nodes[buffer][shader].emplace_back(node, i);
m_mb_map[buffer] = mesh;
if (anode && !added_skinning &&
@ -391,6 +397,31 @@ start:
mapped_addr += extra;
}
for (auto& p : m_dynamic_spm_buffers)
{
for (auto& q : p.second)
{
const size_t dynamic_spm_size = sizeof(ObjectData) +
getPadding(sizeof(ObjectData), sbo_alignment);
if (written_size + dynamic_spm_size > m_sbo_data->getSize())
{
min_size = (written_size + dynamic_spm_size) * 2;
goto start;
}
irr::scene::ISceneNode* node = q.second;
const irr::video::SMaterial& m = node->getMaterial(0);
TexturesList textures = getTexturesList(m);
const irr::video::ITexture** list = &textures[0];
int material_id = m_texture_descriptor->getTextureID(list);
ObjectData* data = (ObjectData*)mapped_addr;
data->init(node, material_id, -1, 0);
m_materials[q.first] = material_id;
written_size += dynamic_spm_size;
mapped_addr += dynamic_spm_size;
}
}
m_dynamic_spm_padded_size = written_size - skinning_data_padded_size;
const bool use_base_vertex = GEVulkanFeatures::supportsBaseVertexRendering();
const bool bind_mesh_textures =
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
@ -710,14 +741,16 @@ start:
m_materials_padded_size = materials_padded_size;
}
// Make sure dynamic offsets of materials won't become invalid
if (written_size + materials_padded_size > m_sbo_data->getSize())
// Make sure dynamic offsets won't become invalid
if (skinning_data_padded_size + (object_data_padded_size * 2) +
(materials_padded_size * 2) > m_sbo_data->getSize())
{
min_size = written_size + materials_padded_size;
min_size = skinning_data_padded_size +
(object_data_padded_size * 2) + (materials_padded_size * 2);
goto start;
}
}
else if (!use_base_vertex)
else
{
// Make sure dynamic offset of objects won't become invalid
if (skinning_data_padded_size + (object_data_padded_size * 2) >
@ -1056,35 +1089,29 @@ start:
void GEVulkanDrawCall::createVulkanData()
{
GEVulkanDriver* vk = getVKDriver();
const bool use_dynamic =
!GEVulkanFeatures::supportsBaseVertexRendering() ||
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
// m_data_layout
VkDescriptorSetLayoutBinding camera_layout_binding = {};
camera_layout_binding.binding = 0;
camera_layout_binding.descriptorCount = 1;
camera_layout_binding.descriptorType = use_dynamic ?
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC :
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
camera_layout_binding.descriptorType =
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
camera_layout_binding.pImmutableSamplers = NULL;
camera_layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkDescriptorSetLayoutBinding object_data_layout_binding = {};
object_data_layout_binding.binding = 1;
object_data_layout_binding.descriptorCount = 1;
object_data_layout_binding.descriptorType = use_dynamic ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
object_data_layout_binding.descriptorType =
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
object_data_layout_binding.pImmutableSamplers = NULL;
object_data_layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkDescriptorSetLayoutBinding skinning_layout_binding = {};
skinning_layout_binding.binding = 2;
skinning_layout_binding.descriptorCount = 1;
skinning_layout_binding.descriptorType = use_dynamic ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
skinning_layout_binding.descriptorType =
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
skinning_layout_binding.pImmutableSamplers = NULL;
skinning_layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
@ -1125,15 +1152,11 @@ void GEVulkanDrawCall::createVulkanData()
std::vector<VkDescriptorPoolSize> sizes =
{
{
use_dynamic ?
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC :
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
vk->getMaxFrameInFlight() + 1
},
{
use_dynamic ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
(vk->getMaxFrameInFlight() + 1) * 2
}
};
@ -1280,6 +1303,27 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk,
}
} // uploadDynamicData
// ----------------------------------------------------------------------------
void GEVulkanDrawCall::bindBaseVertex(GEVulkanDriver* vk, VkCommandBuffer cmd)
{
GEVulkanMeshCache* mc = vk->getVulkanMeshCache();
std::array<VkBuffer, 2> vertex_buffer =
{{
mc->getBuffer(),
mc->getBuffer()
}};
std::array<VkDeviceSize, 2> offsets =
{{
0,
mc->getSkinningVBOOffset()
}};
vkCmdBindVertexBuffers(cmd, 0, vertex_buffer.size(),
vertex_buffer.data(), offsets.data());
vkCmdBindIndexBuffer(cmd, mc->getBuffer(), mc->getIBOOffset(),
VK_INDEX_TYPE_UINT16);
} // bindBaseVertex
// ----------------------------------------------------------------------------
void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
VkCommandBuffer custom_cmd)
@ -1296,25 +1340,6 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
updateDataDescriptorSets(vk);
m_texture_descriptor->updateDescriptor();
if (use_base_vertex)
{
GEVulkanMeshCache* mc = vk->getVulkanMeshCache();
std::array<VkBuffer, 2> vertex_buffer =
{{
mc->getBuffer(),
mc->getBuffer()
}};
std::array<VkDeviceSize, 2> offsets =
{{
0,
mc->getSkinningVBOOffset()
}};
vkCmdBindVertexBuffers(cmd, 0, vertex_buffer.size(),
vertex_buffer.data(), offsets.data());
vkCmdBindIndexBuffer(cmd, mc->getBuffer(), mc->getIBOOffset(),
VK_INDEX_TYPE_UINT16);
}
VkViewport vp;
float scale = getGEConfig()->m_render_scale;
@ -1338,13 +1363,17 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
std::string cur_pipeline = m_cmds[0].m_shader;
bool drawn_skybox = false;
size_t sbo_alignment = m_limits.minStorageBufferOffsetAlignment;
const size_t dynamic_spm_size = sizeof(ObjectData) + getPadding(
sizeof(ObjectData), sbo_alignment);
size_t dynamic_spm_offset = 0;
if (bind_mesh_textures)
{
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 0, 1, m_texture_descriptor->getDescriptorSet(),
0, NULL);
std::array<uint32_t, 4> material_offsets =
std::array<uint32_t, 4> dynamic_offsets =
{{
0u,
0u,
@ -1358,16 +1387,39 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
GEVulkanDynamicBuffer::supportsHostTransfer() ?
m_dynamic_data->getHostBuffer()[current_buffer_idx] :
m_dynamic_data->getLocalBuffer()[current_buffer_idx];
bool rebind_base_vertex = true;
for (unsigned i = 0; i < m_cmds.size(); i++)
{
if (m_cmds[i].m_shader != cur_pipeline)
{
bindPipeline(cmd, cur_pipeline);
material_offsets[3] = m_materials_data[cur_pipeline].first;
auto it = m_dynamic_spm_buffers.find(cur_pipeline);
if (it != m_dynamic_spm_buffers.end() && !it->second.empty())
{
rebind_base_vertex = true;
for (auto& buf : it->second)
{
dynamic_offsets[1] = dynamic_spm_offset;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout,
1, 1, &m_data_descriptor_sets[current_buffer_idx],
dynamic_offsets.size(), dynamic_offsets.data());
buf.first->drawDynamicVertexIndexBuffer(cmd,
current_buffer_idx);
dynamic_spm_offset += dynamic_spm_size;
}
}
if (rebind_base_vertex)
{
bindBaseVertex(vk, cmd);
rebind_base_vertex = false;
}
dynamic_offsets[1] = m_dynamic_spm_padded_size;
dynamic_offsets[3] = m_materials_data[cur_pipeline].first;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1, 1,
&m_data_descriptor_sets[current_buffer_idx],
material_offsets.size(), material_offsets.data());
dynamic_offsets.size(), dynamic_offsets.data());
vkCmdDrawIndexedIndirect(cmd, indirect_buffer, indirect_offset,
draw_count, indirect_size);
indirect_offset += draw_count * indirect_size;
@ -1388,26 +1440,76 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
draw_count++;
}
bindPipeline(cmd, m_cmds.back().m_shader);
material_offsets[3] = m_materials_data[m_cmds.back().m_shader].first;
auto it = m_dynamic_spm_buffers.find(m_cmds.back().m_shader);
if (it != m_dynamic_spm_buffers.end() && !it->second.empty())
{
rebind_base_vertex = true;
for (auto& buf : it->second)
{
dynamic_offsets[1] = dynamic_spm_offset;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1, 1,
&m_data_descriptor_sets[current_buffer_idx],
dynamic_offsets.size(), dynamic_offsets.data());
buf.first->drawDynamicVertexIndexBuffer(cmd,
current_buffer_idx);
dynamic_spm_offset += dynamic_spm_size;
}
}
if (rebind_base_vertex)
bindBaseVertex(vk, cmd);
dynamic_offsets[1] = m_dynamic_spm_padded_size;
dynamic_offsets[3] = m_materials_data[m_cmds.back().m_shader].first;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1, 1,
&m_data_descriptor_sets[current_buffer_idx],
material_offsets.size(), material_offsets.data());
dynamic_offsets.size(), dynamic_offsets.data());
vkCmdDrawIndexedIndirect(cmd, indirect_buffer, indirect_offset,
draw_count, indirect_size);
}
else
{
int cur_mid = m_materials[m_cmds[0].m_mb];
std::array<uint32_t, 3> dynamic_offsets =
{{
0u,
0u,
0u,
}};
bool rebind_base_vertex = true;
int cur_mid = -1;
bindPipeline(cmd, cur_pipeline);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 0, 1,
&m_texture_descriptor->getDescriptorSet()[cur_mid], 0, NULL);
if (use_base_vertex)
auto it = m_dynamic_spm_buffers.find(cur_pipeline);
if (it != m_dynamic_spm_buffers.end() && !it->second.empty())
{
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1, 1,
&m_data_descriptor_sets[current_buffer_idx], 0, NULL);
rebind_base_vertex = true;
for (auto& buf : it->second)
{
dynamic_offsets[1] = dynamic_spm_offset;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout,
1, 1, &m_data_descriptor_sets[current_buffer_idx],
dynamic_offsets.size(), dynamic_offsets.data());
int dy_mat = m_materials[buf.first];
if (dy_mat != cur_mid)
{
cur_mid = dy_mat;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 0, 1,
&m_texture_descriptor->getDescriptorSet()[cur_mid], 0,
NULL);
}
buf.first->drawDynamicVertexIndexBuffer(cmd,
current_buffer_idx);
dynamic_spm_offset += dynamic_spm_size;
}
}
if (cur_mid != m_materials[m_cmds[0].m_mb])
{
cur_mid = m_materials[m_cmds[0].m_mb];
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 0, 1,
&m_texture_descriptor->getDescriptorSet()[cur_mid], 0, NULL);
}
for (unsigned i = 0; i < m_cmds.size(); i++)
{
@ -1422,14 +1524,39 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
&m_texture_descriptor->getDescriptorSet()[cur_mid], 0,
NULL);
if (use_base_vertex)
rebind_base_vertex = true;
}
if (m_cmds[i].m_shader != cur_pipeline)
{
cur_pipeline = m_cmds[i].m_shader;
bindPipeline(cmd, cur_pipeline);
auto it = m_dynamic_spm_buffers.find(cur_pipeline);
if (it != m_dynamic_spm_buffers.end() && !it->second.empty())
{
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1,
1, &m_data_descriptor_sets[current_buffer_idx], 0,
NULL);
rebind_base_vertex = true;
for (auto& buf : it->second)
{
dynamic_offsets[1] = dynamic_spm_offset;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout,
1, 1, &m_data_descriptor_sets[current_buffer_idx],
dynamic_offsets.size(), dynamic_offsets.data());
int dy_mat = m_materials[buf.first];
if (dy_mat != cur_mid)
{
cur_mid = dy_mat;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 0, 1,
&m_texture_descriptor->getDescriptorSet()
[cur_mid], 0, NULL);
}
buf.first->drawDynamicVertexIndexBuffer(cmd,
current_buffer_idx);
dynamic_spm_offset += dynamic_spm_size;
}
}
}
int mid = m_materials[m_cmds[i].m_mb];
if (cur_mid != mid)
{
@ -1439,19 +1566,20 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
&m_texture_descriptor->getDescriptorSet()[cur_mid], 0,
NULL);
}
if (m_cmds[i].m_shader != cur_pipeline)
if (use_base_vertex && rebind_base_vertex)
{
cur_pipeline = m_cmds[i].m_shader;
bindPipeline(cmd, cur_pipeline);
bindBaseVertex(vk, cmd);
rebind_base_vertex = false;
dynamic_offsets[1] = m_dynamic_spm_padded_size;
vkCmdBindDescriptorSets(cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1, 1,
&m_data_descriptor_sets[current_buffer_idx],
dynamic_offsets.size(), dynamic_offsets.data());
}
if (!use_base_vertex)
{
std::array<uint32_t, 3> dynamic_offsets =
{{
0u,
m_cmds[i].m_dynamic_offset,
0u
}};
dynamic_offsets[1] = m_dynamic_spm_padded_size +
m_cmds[i].m_dynamic_offset;
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 1, 1,
&m_data_descriptor_sets[current_buffer_idx],
@ -1521,7 +1649,6 @@ void GEVulkanDrawCall::updateDataDescriptorSets(GEVulkanDriver* vk)
GEVulkanFeatures::supportsBaseVertexRendering();
const bool bind_mesh_textures =
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
const bool use_dynamic = !use_base_vertex || bind_mesh_textures;
for (unsigned i = 0; i < m_data_descriptor_sets.size(); i++)
{
VkDescriptorBufferInfo ubo_info;
@ -1537,9 +1664,7 @@ void GEVulkanDrawCall::updateDataDescriptorSets(GEVulkanDriver* vk)
data_set[0].dstSet = m_data_descriptor_sets[i];
data_set[0].dstBinding = 0;
data_set[0].dstArrayElement = 0;
data_set[0].descriptorType = use_dynamic ?
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC :
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
data_set[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
data_set[0].descriptorCount = 1;
data_set[0].pBufferInfo = &ubo_info;
@ -1552,9 +1677,7 @@ void GEVulkanDrawCall::updateDataDescriptorSets(GEVulkanDriver* vk)
data_set[1].dstSet = m_data_descriptor_sets[i];
data_set[1].dstBinding = 1;
data_set[1].dstArrayElement = 0;
data_set[1].descriptorType = use_dynamic ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
data_set[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
data_set[1].descriptorCount = 1;
data_set[1].pBufferInfo = &sbo_info_objects;
@ -1568,9 +1691,7 @@ void GEVulkanDrawCall::updateDataDescriptorSets(GEVulkanDriver* vk)
data_set[2].dstSet = m_data_descriptor_sets[i];
data_set[2].dstBinding = 2;
data_set[2].dstArrayElement = 0;
data_set[2].descriptorType = use_dynamic ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; ;
data_set[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
data_set[2].descriptorCount = 1;
data_set[2].pBufferInfo = &sbo_info_skinning;

View File

@ -36,6 +36,7 @@ class GEVulkanAnimatedMeshSceneNode;
class GEVulkanCameraSceneNode;
class GEVulkanDriver;
class GEVulkanDynamicBuffer;
class GEVulkanDynamicSPMBuffer;
class GEVulkanTextureDescriptor;
struct ObjectData
@ -114,6 +115,10 @@ private:
std::unordered_map<GESPMBuffer*, irr::scene::IMesh*> m_mb_map;
std::unordered_map<std::string, std::vector<
std::pair<GEVulkanDynamicSPMBuffer*, irr::scene::ISceneNode*> > >
m_dynamic_spm_buffers;
GECullingTool* m_culling_tool;
std::vector<DrawCallData> m_cmds;
@ -132,6 +137,8 @@ private:
size_t m_materials_padded_size;
size_t m_dynamic_spm_padded_size;
bool m_update_data_descriptor_sets;
VkDescriptorSetLayout m_data_layout;
@ -188,6 +195,8 @@ private:
size_t getInitialSBOSize() const;
// ------------------------------------------------------------------------
void updateDataDescriptorSets(GEVulkanDriver* vk);
// ------------------------------------------------------------------------
void bindBaseVertex(GEVulkanDriver* vk, VkCommandBuffer cmd);
public:
// ------------------------------------------------------------------------
GEVulkanDrawCall();
@ -226,6 +235,7 @@ public:
m_materials.clear();
m_skinning_nodes.clear();
m_materials_data.clear();
m_dynamic_spm_buffers.clear();
}
}; // GEVulkanDrawCall

View File

@ -11,6 +11,7 @@
#include "ge_vulkan_command_loader.hpp"
#include "ge_vulkan_depth_texture.hpp"
#include "ge_vulkan_draw_call.hpp"
#include "ge_vulkan_dynamic_spm_buffer.hpp"
#include "ge_vulkan_fbo_texture.hpp"
#include "ge_vulkan_features.hpp"
#include "ge_vulkan_mesh_cache.hpp"
@ -1680,6 +1681,9 @@ bool GEVulkanDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
sourceRect))
return false;
for (GEVulkanDynamicSPMBuffer* buffer : m_dynamic_spm_buffers)
buffer->updateVertexIndexBuffer(m_current_buffer_idx);
m_clear_color = color;
PrimitivesDrawn = m_rtt_polycount;
m_rtt_polycount = 0;

View File

@ -1,8 +1,11 @@
#include "ge_vulkan_dynamic_spm_buffer.hpp"
#include "ge_main.hpp"
#include "ge_vulkan_driver.hpp"
#include "ge_vulkan_dynamic_buffer.hpp"
#include <cmath>
namespace GE
{
@ -15,13 +18,54 @@ GEVulkanDynamicSPMBuffer::GEVulkanDynamicSPMBuffer()
m_index_buffer = new GEVulkanDynamicBuffer(
VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 100,
GEVulkanDriver::getMaxFrameInFlight() + 1, 0);
getVKDriver()->addDynamicSPMBuffer(this);
} // GEVulkanDynamicSPMBuffer
// ----------------------------------------------------------------------------
GEVulkanDynamicSPMBuffer::~GEVulkanDynamicSPMBuffer()
{
getVKDriver()->removeDynamicSPMBuffer(this);
delete m_vertex_buffer;
delete m_index_buffer;
} // ~GEVulkanDynamicSPMBuffer
// ----------------------------------------------------------------------------
void GEVulkanDynamicSPMBuffer::updateVertexIndexBuffer(int buffer_index)
{
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);
uint8_t* mapped_addr = (uint8_t*)m_vertex_buffer->getMappedAddr()
[buffer_index];
for (unsigned i = 0; 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);
} // updateVertexIndexBuffer
// ----------------------------------------------------------------------------
void GEVulkanDynamicSPMBuffer::drawDynamicVertexIndexBuffer(VkCommandBuffer cmd,
int buffer_index)
{
std::array<VkBuffer, 2> vertex_buffer =
{{
m_vertex_buffer->getHostBuffer()[buffer_index],
m_vertex_buffer->getHostBuffer()[buffer_index]
}};
std::array<VkDeviceSize, 2> offsets =
{{
0,
0
}};
vkCmdBindVertexBuffers(cmd, 0, vertex_buffer.size(), vertex_buffer.data(),
offsets.data());
VkBuffer index_buffer = m_index_buffer->getHostBuffer()[buffer_index];
vkCmdBindIndexBuffer(cmd, index_buffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdDrawIndexed(cmd, getIndexCount(), 1, 0, 0, 0);
} // drawDynamicVertexIndexBuffer
} // end namespace GE