Use multi-draw indirect if supported
This commit is contained in:
parent
7f31ffa552
commit
d325e33fc0
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ bool supportsDifferentTexturePerDraw();
|
||||
bool supportsPartiallyBound();
|
||||
// ----------------------------------------------------------------------------
|
||||
bool supportsBindMeshTexturesAtOnce();
|
||||
// ----------------------------------------------------------------------------
|
||||
bool supportsMultiDrawIndirect();
|
||||
}; // GEVulkanFeatures
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user