Add rendering for GEVulkanDynamicSPMBuffer
This commit is contained in:
parent
392bdbf78b
commit
1d00e44f97
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user