From 1d00e44f97e30549369e2e18e1f99dbc95d25dc3 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 1 Dec 2022 16:16:58 +0800 Subject: [PATCH] Add rendering for GEVulkanDynamicSPMBuffer --- .../include/ge_vulkan_driver.hpp | 7 + .../include/ge_vulkan_dynamic_spm_buffer.hpp | 4 + .../src/ge_vulkan_draw_call.cpp | 279 +++++++++++++----- .../src/ge_vulkan_draw_call.hpp | 10 + lib/graphics_engine/src/ge_vulkan_driver.cpp | 4 + .../src/ge_vulkan_dynamic_spm_buffer.cpp | 44 +++ 6 files changed, 269 insertions(+), 79 deletions(-) diff --git a/lib/graphics_engine/include/ge_vulkan_driver.hpp b/lib/graphics_engine/include/ge_vulkan_driver.hpp index 9b524c3c6ca..ac74f8208d7 100644 --- a/lib/graphics_engine/include/ge_vulkan_driver.hpp +++ b/lib/graphics_engine/include/ge_vulkan_driver.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -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 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 > m_draw_calls_cache; GESPM* m_billboard_quad; int m_current_buffer_idx; + std::set m_dynamic_spm_buffers; void createInstance(SDL_Window* window); void findPhysicalDevice(); 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 97e33560f77..c39a9ef326c 100644 --- a/lib/graphics_engine/include/ge_vulkan_dynamic_spm_buffer.hpp +++ b/lib/graphics_engine/include/ge_vulkan_dynamic_spm_buffer.hpp @@ -30,6 +30,10 @@ class GEVulkanDynamicSPMBuffer : public GESPMBuffer virtual void createVertexIndexBuffer() {} // ------------------------------------------------------------------------ virtual void destroyVertexIndexBuffer() {} + // ------------------------------------------------------------------------ + void updateVertexIndexBuffer(int buffer_index); + // ------------------------------------------------------------------------ + void drawDynamicVertexIndexBuffer(VkCommandBuffer cmd, int buffer_index); }; } // end namespace GE diff --git a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp index 3609e0d814b..2c2bc57513f 100644 --- a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp +++ b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp @@ -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 @@ void GEVulkanDrawCall::generate(GEVulkanDriver* vk) 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 @@ void GEVulkanDrawCall::generate(GEVulkanDriver* vk) 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 @@ void GEVulkanDrawCall::createPipeline(GEVulkanDriver* vk, 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 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 vertex_buffer = + {{ + mc->getBuffer(), + mc->getBuffer() + }}; + std::array 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 vertex_buffer = - {{ - mc->getBuffer(), - mc->getBuffer() - }}; - std::array 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 material_offsets = + std::array 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 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()) + { + 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]) { - vkCmdBindDescriptorSets(cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1, 1, - &m_data_descriptor_sets[current_buffer_idx], 0, NULL); + 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 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; diff --git a/lib/graphics_engine/src/ge_vulkan_draw_call.hpp b/lib/graphics_engine/src/ge_vulkan_draw_call.hpp index 3efae3052ad..4dc705f7c2e 100644 --- a/lib/graphics_engine/src/ge_vulkan_draw_call.hpp +++ b/lib/graphics_engine/src/ge_vulkan_draw_call.hpp @@ -36,6 +36,7 @@ class GEVulkanAnimatedMeshSceneNode; class GEVulkanCameraSceneNode; class GEVulkanDriver; class GEVulkanDynamicBuffer; +class GEVulkanDynamicSPMBuffer; class GEVulkanTextureDescriptor; struct ObjectData @@ -114,6 +115,10 @@ class GEVulkanDrawCall std::unordered_map m_mb_map; + std::unordered_map > > + m_dynamic_spm_buffers; + GECullingTool* m_culling_tool; std::vector m_cmds; @@ -132,6 +137,8 @@ class GEVulkanDrawCall 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 @@ class GEVulkanDrawCall size_t getInitialSBOSize() const; // ------------------------------------------------------------------------ void updateDataDescriptorSets(GEVulkanDriver* vk); + // ------------------------------------------------------------------------ + void bindBaseVertex(GEVulkanDriver* vk, VkCommandBuffer cmd); public: // ------------------------------------------------------------------------ GEVulkanDrawCall(); @@ -226,6 +235,7 @@ class GEVulkanDrawCall m_materials.clear(); m_skinning_nodes.clear(); m_materials_data.clear(); + m_dynamic_spm_buffers.clear(); } }; // GEVulkanDrawCall diff --git a/lib/graphics_engine/src/ge_vulkan_driver.cpp b/lib/graphics_engine/src/ge_vulkan_driver.cpp index 1883b6dad10..5eb266f4275 100644 --- a/lib/graphics_engine/src/ge_vulkan_driver.cpp +++ b/lib/graphics_engine/src/ge_vulkan_driver.cpp @@ -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; 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 b4e6aca057d..a4d2c0da462 100644 --- a/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp @@ -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 + 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 vertex_buffer = + {{ + m_vertex_buffer->getHostBuffer()[buffer_index], + m_vertex_buffer->getHostBuffer()[buffer_index] + }}; + std::array 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