mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-16 12:36:59 +02:00
[vk] VK_EXT_multi_draw
This commit is contained in:
parent
0c26513484
commit
977904cd27
5 changed files with 83 additions and 10 deletions
|
|
@ -197,6 +197,11 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
|
||||||
fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler),
|
fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler),
|
||||||
wfi_event(device.GetLogical().CreateEvent()) {
|
wfi_event(device.GetLogical().CreateEvent()) {
|
||||||
scheduler.SetQueryCache(query_cache);
|
scheduler.SetQueryCache(query_cache);
|
||||||
|
|
||||||
|
// Log multi-draw support
|
||||||
|
if (device.IsExtMultiDrawSupported()) {
|
||||||
|
LOG_INFO(Render_Vulkan, "VK_EXT_multi_draw is enabled for optimized draw calls");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterizerVulkan::~RasterizerVulkan() = default;
|
RasterizerVulkan::~RasterizerVulkan() = default;
|
||||||
|
|
@ -234,16 +239,44 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
||||||
const u32 num_instances{instance_count};
|
const u32 num_instances{instance_count};
|
||||||
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
|
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
|
||||||
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
|
|
||||||
if (draw_params.is_indexed) {
|
// Use VK_EXT_multi_draw if available (single draw becomes multi-draw with count=1)
|
||||||
cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances,
|
if (device.IsExtMultiDrawSupported()) {
|
||||||
draw_params.first_index, draw_params.base_vertex,
|
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
|
||||||
draw_params.base_instance);
|
if (draw_params.is_indexed) {
|
||||||
} else {
|
// Use multi-draw indexed with single draw
|
||||||
cmdbuf.Draw(draw_params.num_vertices, draw_params.num_instances,
|
const VkMultiDrawIndexedInfoEXT multi_draw_info{
|
||||||
draw_params.base_vertex, draw_params.base_instance);
|
.firstIndex = draw_params.first_index,
|
||||||
}
|
.indexCount = draw_params.num_vertices,
|
||||||
});
|
};
|
||||||
|
const int32_t vertex_offset = static_cast<int32_t>(draw_params.base_vertex);
|
||||||
|
cmdbuf.DrawMultiIndexedEXT(1, &multi_draw_info, draw_params.num_instances,
|
||||||
|
draw_params.base_instance,
|
||||||
|
sizeof(VkMultiDrawIndexedInfoEXT), &vertex_offset);
|
||||||
|
} else {
|
||||||
|
// Use multi-draw with single draw
|
||||||
|
const VkMultiDrawInfoEXT multi_draw_info{
|
||||||
|
.firstVertex = draw_params.base_vertex,
|
||||||
|
.vertexCount = draw_params.num_vertices,
|
||||||
|
};
|
||||||
|
cmdbuf.DrawMultiEXT(1, &multi_draw_info, draw_params.num_instances,
|
||||||
|
draw_params.base_instance,
|
||||||
|
sizeof(VkMultiDrawInfoEXT));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Fallback to standard draw calls
|
||||||
|
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
|
||||||
|
if (draw_params.is_indexed) {
|
||||||
|
cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances,
|
||||||
|
draw_params.first_index, draw_params.base_vertex,
|
||||||
|
draw_params.base_instance);
|
||||||
|
} else {
|
||||||
|
cmdbuf.Draw(draw_params.num_vertices, draw_params.num_instances,
|
||||||
|
draw_params.base_vertex, draw_params.base_instance);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1126,6 +1126,11 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR;
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR;
|
||||||
SetNext(next, properties.maintenance5);
|
SetNext(next, properties.maintenance5);
|
||||||
}
|
}
|
||||||
|
if (extensions.multi_draw) {
|
||||||
|
properties.multi_draw.sType =
|
||||||
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT;
|
||||||
|
SetNext(next, properties.multi_draw);
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the property fetch.
|
// Perform the property fetch.
|
||||||
physical.GetProperties2(properties2);
|
physical.GetProperties2(properties2);
|
||||||
|
|
@ -1351,6 +1356,17 @@ void Device::RemoveUnsuitableExtensions() {
|
||||||
features.vertex_input_dynamic_state,
|
features.vertex_input_dynamic_state,
|
||||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
|
|
||||||
|
// VK_EXT_multi_draw
|
||||||
|
extensions.multi_draw = features.multi_draw.multiDraw;
|
||||||
|
|
||||||
|
if (extensions.multi_draw) {
|
||||||
|
LOG_INFO(Render_Vulkan, "VK_EXT_multi_draw: maxMultiDrawCount={}",
|
||||||
|
properties.multi_draw.maxMultiDrawCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveExtensionFeatureIfUnsuitable(extensions.multi_draw, features.multi_draw,
|
||||||
|
VK_EXT_MULTI_DRAW_EXTENSION_NAME);
|
||||||
|
|
||||||
// VK_KHR_pipeline_executable_properties
|
// VK_KHR_pipeline_executable_properties
|
||||||
if (Settings::values.renderer_shader_feedback.GetValue()) {
|
if (Settings::values.renderer_shader_feedback.GetValue()) {
|
||||||
extensions.pipeline_executable_properties =
|
extensions.pipeline_executable_properties =
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
||||||
FEATURE(EXT, 4444Formats, 4444_FORMATS, format_a4b4g4r4) \
|
FEATURE(EXT, 4444Formats, 4444_FORMATS, format_a4b4g4r4) \
|
||||||
FEATURE(EXT, IndexTypeUint8, INDEX_TYPE_UINT8, index_type_uint8) \
|
FEATURE(EXT, IndexTypeUint8, INDEX_TYPE_UINT8, index_type_uint8) \
|
||||||
FEATURE(EXT, LineRasterization, LINE_RASTERIZATION, line_rasterization) \
|
FEATURE(EXT, LineRasterization, LINE_RASTERIZATION, line_rasterization) \
|
||||||
|
FEATURE(EXT, MultiDraw, MULTI_DRAW, multi_draw) \
|
||||||
FEATURE(EXT, PrimitiveTopologyListRestart, PRIMITIVE_TOPOLOGY_LIST_RESTART, \
|
FEATURE(EXT, PrimitiveTopologyListRestart, PRIMITIVE_TOPOLOGY_LIST_RESTART, \
|
||||||
primitive_topology_list_restart) \
|
primitive_topology_list_restart) \
|
||||||
FEATURE(EXT, ProvokingVertex, PROVOKING_VERTEX, provoking_vertex) \
|
FEATURE(EXT, ProvokingVertex, PROVOKING_VERTEX, provoking_vertex) \
|
||||||
|
|
@ -818,6 +819,11 @@ public:
|
||||||
return extensions.maintenance6;
|
return extensions.maintenance6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the device supports VK_EXT_multi_draw.
|
||||||
|
bool IsExtMultiDrawSupported() const {
|
||||||
|
return extensions.multi_draw;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the device supports VK_KHR_maintenance7.
|
/// Returns true if the device supports VK_KHR_maintenance7.
|
||||||
bool IsKhrMaintenance7Supported() const {
|
bool IsKhrMaintenance7Supported() const {
|
||||||
return extensions.maintenance7;
|
return extensions.maintenance7;
|
||||||
|
|
@ -950,6 +956,7 @@ private:
|
||||||
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{};
|
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{};
|
||||||
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{};
|
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{};
|
||||||
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
|
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
|
||||||
|
VkPhysicalDeviceMultiDrawPropertiesEXT multi_draw{};
|
||||||
|
|
||||||
VkPhysicalDeviceProperties properties{};
|
VkPhysicalDeviceProperties properties{};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,8 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
||||||
X(vkCmdDrawIndirectCount);
|
X(vkCmdDrawIndirectCount);
|
||||||
X(vkCmdDrawIndexedIndirectCount);
|
X(vkCmdDrawIndexedIndirectCount);
|
||||||
X(vkCmdDrawIndirectByteCountEXT);
|
X(vkCmdDrawIndirectByteCountEXT);
|
||||||
|
X(vkCmdDrawMultiEXT);
|
||||||
|
X(vkCmdDrawMultiIndexedEXT);
|
||||||
X(vkCmdEndConditionalRenderingEXT);
|
X(vkCmdEndConditionalRenderingEXT);
|
||||||
X(vkCmdEndQuery);
|
X(vkCmdEndQuery);
|
||||||
X(vkCmdEndRenderPass);
|
X(vkCmdEndRenderPass);
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,8 @@ struct DeviceDispatch : InstanceDispatch {
|
||||||
PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount{};
|
PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount{};
|
||||||
PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount{};
|
PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount{};
|
||||||
PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT{};
|
PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT{};
|
||||||
|
PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT{};
|
||||||
|
PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT{};
|
||||||
PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT{};
|
PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT{};
|
||||||
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{};
|
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{};
|
||||||
PFN_vkCmdEndQuery vkCmdEndQuery{};
|
PFN_vkCmdEndQuery vkCmdEndQuery{};
|
||||||
|
|
@ -1239,6 +1241,19 @@ public:
|
||||||
counter_buffer_offset, counter_offset, stride);
|
counter_buffer_offset, counter_offset, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawMultiEXT(u32 draw_count, const VkMultiDrawInfoEXT* vertex_info,
|
||||||
|
u32 instance_count, u32 first_instance, u32 stride) const noexcept {
|
||||||
|
dld->vkCmdDrawMultiEXT(handle, draw_count, vertex_info, instance_count, first_instance,
|
||||||
|
stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawMultiIndexedEXT(u32 draw_count, const VkMultiDrawIndexedInfoEXT* index_info,
|
||||||
|
u32 instance_count, u32 first_instance, u32 stride,
|
||||||
|
const int32_t* vertex_offset) const noexcept {
|
||||||
|
dld->vkCmdDrawMultiIndexedEXT(handle, draw_count, index_info, instance_count,
|
||||||
|
first_instance, stride, vertex_offset);
|
||||||
|
}
|
||||||
|
|
||||||
void ClearAttachments(Span<VkClearAttachment> attachments,
|
void ClearAttachments(Span<VkClearAttachment> attachments,
|
||||||
Span<VkClearRect> rects) const noexcept {
|
Span<VkClearRect> rects) const noexcept {
|
||||||
dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(),
|
dld->vkCmdClearAttachments(handle, attachments.size(), attachments.data(), rects.size(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue