Add dynamic descriptor code for some devices

This commit is contained in:
Benau 2022-08-02 00:25:36 +08:00
parent 72b177c354
commit 403f748b4a
6 changed files with 147 additions and 29 deletions

View File

@ -549,25 +549,33 @@ start:
void GEVulkanDrawCall::createVulkanData()
{
GEVulkanDriver* vk = getVKDriver();
const bool use_base_vertex = GEVulkanFeatures::supportsBaseVertexRendering();
// m_data_layout
VkDescriptorSetLayoutBinding camera_layout_binding = {};
camera_layout_binding.binding = 0;
camera_layout_binding.descriptorCount = 1;
camera_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
camera_layout_binding.descriptorType = use_base_vertex ?
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER :
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 = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
object_data_layout_binding.descriptorType = use_base_vertex ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER :
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 = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
skinning_layout_binding.descriptorType = use_base_vertex ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
skinning_layout_binding.pImmutableSamplers = NULL;
skinning_layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
@ -596,8 +604,18 @@ void GEVulkanDrawCall::createVulkanData()
// m_descriptor_pool
std::array<VkDescriptorPoolSize, 2> sizes =
{{
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk->getMaxFrameInFlight() },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk->getMaxFrameInFlight() * 2 }
{
use_base_vertex ?
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER :
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
vk->getMaxFrameInFlight()
},
{
use_base_vertex ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
vk->getMaxFrameInFlight() * 2
}
}};
VkDescriptorPoolCreateInfo pool_info = {};
@ -697,21 +715,63 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk,
m_data_uploading.emplace_back((void*)m_data_padding, sbo_padding);
}
const size_t object_data_size =
sizeof(ObjectData) * m_visible_objects.size();
size_t ubo_alignment = limit.minUniformBufferOffsetAlignment;
size_t ubo_padding = getPadding(
m_skinning_data_padded_size + object_data_size, ubo_alignment);
m_object_data_padded_size = object_data_size + ubo_padding;
// https://github.com/google/filament/pull/3814
// Need both vertex and fragment bit
VkPipelineStageFlags dst_stage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
m_data_uploading.emplace_back((void*)m_visible_objects.data(),
object_data_size);
if (ubo_padding > 0)
m_data_uploading.emplace_back((void*)m_data_padding, ubo_padding);
size_t ubo_alignment = limit.minUniformBufferOffsetAlignment;
size_t ubo_padding = 0;
const bool use_base_vertex = GEVulkanFeatures::supportsBaseVertexRendering();
if (use_base_vertex)
{
const size_t object_data_size =
sizeof(ObjectData) * m_visible_objects.size();
m_data_uploading.emplace_back((void*)m_visible_objects.data(),
object_data_size);
ubo_padding = getPadding(
m_skinning_data_padded_size + object_data_size, ubo_alignment);
if (ubo_padding > 0)
m_data_uploading.emplace_back((void*)m_data_padding, ubo_padding);
m_object_data_padded_size = object_data_size + ubo_padding;
}
else
{
m_object_data_padded_size = 0;
for (unsigned i = 0; i < m_cmds.size(); i++)
{
auto& cmd = m_cmds[i];
size_t instance_size =
cmd.m_cmd.instanceCount * sizeof(ObjectData);
m_data_uploading.emplace_back(
&m_visible_objects[cmd.m_cmd.firstInstance], instance_size);
size_t cur_padding = getPadding(
m_skinning_data_padded_size + m_object_data_padded_size +
instance_size, sbo_alignment);
if (cur_padding > 0)
{
instance_size += cur_padding;
m_data_uploading.emplace_back((void*)m_data_padding,
cur_padding);
}
m_sbo_data_offset.push_back(m_object_data_padded_size);
m_object_data_padded_size += instance_size;
}
}
if (!use_base_vertex)
{
ubo_padding = getPadding(m_skinning_data_padded_size +
m_object_data_padded_size, ubo_alignment);
if (ubo_padding > 0)
{
m_data_uploading.emplace_back((void*)m_data_padding,
ubo_padding);
m_object_data_padded_size += ubo_padding;
}
// Make sure dynamic offset won't become invaild
m_dynamic_data->resizeIfNeeded(m_skinning_data_padded_size +
m_object_data_padded_size * 2 + sizeof(GEVulkanCameraUBO));
}
m_data_uploading.emplace_back(cam->getUBOData(), sizeof(GEVulkanCameraUBO));
const bool use_multidraw = GEVulkanFeatures::supportsMultiDrawIndirect() &&
@ -753,6 +813,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
custom_cmd ? custom_cmd : vk->getCurrentCommandBuffer();
const unsigned cur_frame = vk->getCurrentFrame();
const bool use_base_vertex = GEVulkanFeatures::supportsBaseVertexRendering();
VkDescriptorBufferInfo ubo_info;
ubo_info.buffer = m_dynamic_data->getCurrentBuffer();
ubo_info.offset = m_skinning_data_padded_size + m_object_data_padded_size;
@ -763,7 +824,9 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
data_set[0].dstSet = m_data_descriptor_sets[cur_frame];
data_set[0].dstBinding = 0;
data_set[0].dstArrayElement = 0;
data_set[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
data_set[0].descriptorType = use_base_vertex ?
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER :
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
data_set[0].descriptorCount = 1;
data_set[0].pBufferInfo = &ubo_info;
@ -776,7 +839,9 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
data_set[1].dstSet = m_data_descriptor_sets[cur_frame];
data_set[1].dstBinding = 1;
data_set[1].dstArrayElement = 0;
data_set[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
data_set[1].descriptorType = use_base_vertex ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
data_set[1].descriptorCount = 1;
data_set[1].pBufferInfo = &sbo_info_objects;
@ -789,7 +854,9 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
data_set[2].dstSet = m_data_descriptor_sets[cur_frame];
data_set[2].dstBinding = 2;
data_set[2].dstArrayElement = 0;
data_set[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
data_set[2].descriptorType = use_base_vertex ?
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER :
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; ;
data_set[2].descriptorCount = 1;
data_set[2].pBufferInfo = &sbo_info_skinning;
@ -805,8 +872,12 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
0, NULL);
}
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 1, 1, &m_data_descriptor_sets[cur_frame], 0, NULL);
if (use_base_vertex)
{
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 1, 1, &m_data_descriptor_sets[cur_frame], 0,
NULL);
}
GEVulkanMeshCache* mc = vk->getVulkanMeshCache();
std::array<VkBuffer, 2> vertex_buffer =
@ -900,8 +971,21 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
cur_pipeline = m_cmds[i].m_shader;
bindPipeline(cmd, cur_pipeline);
}
if (!use_base_vertex)
{
std::array<uint32_t, 3> dynamic_offsets =
{{
0u,
uint32_t(m_sbo_data_offset[i]),
0u
}};
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline_layout, 1, 1, &m_data_descriptor_sets[cur_frame],
dynamic_offsets.size(), dynamic_offsets.data());
}
vkCmdDrawIndexed(cmd, cur_cmd.indexCount, cur_cmd.instanceCount,
cur_cmd.firstIndex, cur_cmd.vertexOffset, cur_cmd.firstInstance);
cur_cmd.firstIndex, cur_cmd.vertexOffset,
use_base_vertex ? cur_cmd.firstInstance : 0);
}
}
} // render

View File

@ -104,6 +104,8 @@ private:
std::vector<std::pair<void*, size_t> > m_data_uploading;
std::vector<size_t> m_sbo_data_offset;
// ------------------------------------------------------------------------
void createAllPipelines(GEVulkanDriver* vk);
// ------------------------------------------------------------------------
@ -160,6 +162,7 @@ public:
m_materials.clear();
m_skinning_nodes.clear();
m_data_uploading.clear();
m_sbo_data_offset.clear();
}
}; // GEVulkanDrawCall

View File

@ -164,13 +164,8 @@ void GEVulkanDynamicBuffer::setCurrentData(const std::vector<
size_t size = 0;
for (auto& p : data)
size += p.second;
if (size > m_size)
{
destroy();
m_size = size + 100;
for (unsigned i = 0; i < GEVulkanDriver::getMaxFrameInFlight(); i++)
initPerFrame(i);
}
resizeIfNeeded(size);
m_real_size = size;
if (size == 0 || m_mapped_addr[cur_frame] == NULL)
return;
@ -193,6 +188,18 @@ void GEVulkanDynamicBuffer::setCurrentData(const std::vector<
}
} // setCurrentData
// ----------------------------------------------------------------------------
void GEVulkanDynamicBuffer::resizeIfNeeded(size_t new_size)
{
if (new_size > m_size)
{
destroy();
m_size = new_size + 100;
for (unsigned i = 0; i < GEVulkanDriver::getMaxFrameInFlight(); i++)
initPerFrame(i);
}
} // resizeIfNeeded
// ----------------------------------------------------------------------------
VkBuffer GEVulkanDynamicBuffer::getCurrentBuffer() const
{

View File

@ -58,6 +58,8 @@ public:
// ------------------------------------------------------------------------
VkBuffer getCurrentBuffer() const;
// ------------------------------------------------------------------------
void resizeIfNeeded(size_t new_size);
// ------------------------------------------------------------------------
size_t getRealSize() const { return m_real_size; }
}; // GEVulkanDynamicBuffer

View File

@ -24,6 +24,7 @@ bool g_supports_non_uniform_indexing = false;
bool g_supports_partially_bound = false;
uint32_t g_max_sampler_supported = 0;
bool g_supports_multi_draw_indirect = false;
bool g_supports_base_vertex_rendering = true;
} // GEVulkanFeatures
// ============================================================================
@ -124,6 +125,16 @@ void GEVulkanFeatures::init(GEVulkanDriver* vk)
g_max_sampler_supported >= max_sampler_size;
}
}
#if defined(__APPLE__)
MVKPhysicalDeviceMetalFeatures mvk_features = {};
size_t mvk_features_size = sizeof(MVKPhysicalDeviceMetalFeatures);
vkGetPhysicalDeviceMetalFeaturesMVK(vk->getPhysicalDevice(), &mvk_features,
&mvk_features_size);
g_supports_base_vertex_rendering = mvk_features.baseVertexInstanceDrawing;
if (!g_supports_base_vertex_rendering)
g_supports_multi_draw_indirect = false;
#endif
} // init
// ----------------------------------------------------------------------------
@ -147,6 +158,9 @@ void GEVulkanFeatures::printStats()
os::Printer::log(
"Vulkan supports multi-draw indirect",
g_supports_multi_draw_indirect ? "true" : "false");
os::Printer::log(
"Vulkan supports base vertex rendering",
g_supports_base_vertex_rendering ? "true" : "false");
os::Printer::log(
"Vulkan descriptor indexes can be dynamically non-uniform",
g_supports_non_uniform_indexing ? "true" : "false");
@ -214,4 +228,10 @@ bool GEVulkanFeatures::supportsMultiDrawIndirect()
return g_supports_multi_draw_indirect;
} // supportsBindMeshTexturesAtOnce
// ----------------------------------------------------------------------------
bool GEVulkanFeatures::supportsBaseVertexRendering()
{
return g_supports_base_vertex_rendering;
} // supportsBindMeshTexturesAtOnce
}

View File

@ -30,6 +30,8 @@ bool supportsPartiallyBound();
bool supportsBindMeshTexturesAtOnce();
// ----------------------------------------------------------------------------
bool supportsMultiDrawIndirect();
// ----------------------------------------------------------------------------
bool supportsBaseVertexRendering();
}; // GEVulkanFeatures
}