Use multi-draw indirect if supported

This commit is contained in:
Benau 2022-07-23 14:02:37 +08:00
parent 7f31ffa552
commit d325e33fc0
4 changed files with 63 additions and 18 deletions

View File

@ -405,9 +405,15 @@ void GEVulkanDrawCall::createVulkanData()
size_t size = m_visible_objects.size();
if (m_visible_objects.empty())
size = 100;
m_dynamic_data = new GEVulkanDynamicBuffer(GVDBT_GPU_RAM,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
const bool use_multidraw = GEVulkanFeatures::supportsMultiDrawIndirect() &&
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
VkBufferUsageFlags flags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
if (use_multidraw)
flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
m_dynamic_data = new GEVulkanDynamicBuffer(GVDBT_GPU_RAM, flags,
(sizeof(ObjectData) * size) + sizeof(GEVulkanCameraUBO));
} // createVulkanData
@ -428,11 +434,24 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk,
ubo_padding = 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;
std::vector<std::pair<void*, size_t> > data;
data.emplace_back((void*)m_visible_objects.data(), object_data_size);
if (ubo_padding > 0)
data.emplace_back((void*)m_object_data_padding, ubo_padding);
data.emplace_back(cam->getUBOData(), sizeof(GEVulkanCameraUBO));
const bool use_multidraw = GEVulkanFeatures::supportsMultiDrawIndirect() &&
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
if (use_multidraw)
{
data.emplace_back(m_cmds.data(),
sizeof(VkDrawIndexedIndirectCommand) * m_cmds.size());
dst_stage |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
}
m_dynamic_data->setCurrentData(data);
VkBufferMemoryBarrier barrier = {};
@ -444,12 +463,8 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk,
barrier.buffer = m_dynamic_data->getCurrentBuffer();
barrier.size = m_dynamic_data->getRealSize();
// https://github.com/google/filament/pull/3814
// Need both vertex and fragment bit
vkCmdPipelineBarrier(vk->getCurrentCommandBuffer(),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 1, &barrier, 0,
VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage, 0, 0, NULL, 1, &barrier, 0,
NULL);
} // uploadDynamicData
@ -533,19 +548,31 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam)
scissor.extent.height = vp.height;
vkCmdSetScissor(vk->getCurrentCommandBuffer(), 0, 1, &scissor);
for (unsigned i = 0; i < m_cmds.size(); i++)
const bool use_multidraw = GEVulkanFeatures::supportsMultiDrawIndirect() &&
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
if (use_multidraw)
{
if (!GEVulkanFeatures::supportsBindMeshTexturesAtOnce())
vkCmdDrawIndexedIndirect(vk->getCurrentCommandBuffer(),
m_dynamic_data->getCurrentBuffer(),
m_object_data_padded_size + sizeof(GEVulkanCameraUBO),
m_cmds.size(), sizeof(VkDrawIndexedIndirectCommand));
}
else
{
for (unsigned i = 0; i < m_cmds.size(); i++)
{
vkCmdBindDescriptorSets(vk->getCurrentCommandBuffer(),
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1,
&m_texture_descriptor->getDescriptorSet()[m_materials[i]], 0,
NULL);
if (!GEVulkanFeatures::supportsBindMeshTexturesAtOnce())
{
vkCmdBindDescriptorSets(vk->getCurrentCommandBuffer(),
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1,
&m_texture_descriptor->getDescriptorSet()[m_materials[i]],
0, NULL);
}
const VkDrawIndexedIndirectCommand& cmd = m_cmds[i];
vkCmdDrawIndexed(vk->getCurrentCommandBuffer(), cmd.indexCount,
cmd.instanceCount, cmd.firstIndex, cmd.vertexOffset,
cmd.firstInstance);
}
const VkDrawIndexedIndirectCommand& cmd = m_cmds[i];
vkCmdDrawIndexed(vk->getCurrentCommandBuffer(), cmd.indexCount,
cmd.instanceCount, cmd.firstIndex, cmd.vertexOffset,
cmd.firstInstance);
}
} // render

View File

@ -956,6 +956,10 @@ void GEVulkanDriver::createDevice()
VkPhysicalDeviceFeatures device_features = {};
device_features.shaderSampledImageArrayDynamicIndexing =
GEVulkanFeatures::supportsBindTexturesAtOnce();
device_features.multiDrawIndirect =
GEVulkanFeatures::supportsMultiDrawIndirect();
device_features.drawIndirectFirstInstance =
GEVulkanFeatures::supportsMultiDrawIndirect();
VkPhysicalDeviceVulkan12Features vulkan12_features = {};
vulkan12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;

View File

@ -23,6 +23,7 @@ bool g_supports_descriptor_indexing = false;
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;
} // GEVulkanFeatures
// ============================================================================
@ -51,6 +52,8 @@ void GEVulkanFeatures::init(GEVulkanDriver* vk)
dynamic_indexing = false;
g_supports_bind_textures_at_once = false;
}
g_supports_multi_draw_indirect = vk->getPhysicalDeviceFeatures().multiDrawIndirect &&
vk->getPhysicalDeviceFeatures().drawIndirectFirstInstance;
VkFormatProperties format_properties = {};
vkGetPhysicalDeviceFormatProperties(vk->getPhysicalDevice(),
@ -141,6 +144,9 @@ void GEVulkanFeatures::printStats()
os::Printer::log(
"Vulkan supports VK_EXT_descriptor_indexing",
g_supports_descriptor_indexing ? "true" : "false");
os::Printer::log(
"Vulkan supports multi-draw indirect",
g_supports_multi_draw_indirect ? "true" : "false");
os::Printer::log(
"Vulkan descriptor indexes can be dynamically non-uniform",
g_supports_non_uniform_indexing ? "true" : "false");
@ -202,4 +208,10 @@ bool GEVulkanFeatures::supportsBindMeshTexturesAtOnce()
return g_max_sampler_supported >= sampler_count;
} // supportsBindMeshTexturesAtOnce
// ----------------------------------------------------------------------------
bool GEVulkanFeatures::supportsMultiDrawIndirect()
{
return g_supports_multi_draw_indirect;
} // supportsBindMeshTexturesAtOnce
}

View File

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