renderer_vulkan: Fallback to software shaders on unsupported topology
* MoltenVK does not support triangle fans
This commit is contained in:
@ -61,7 +61,7 @@ constexpr static std::array RASTERIZER_SETS = {
|
|||||||
vk::DescriptorType::eStorageImage,
|
vk::DescriptorType::eStorageImage,
|
||||||
vk::DescriptorType::eStorageImage,
|
vk::DescriptorType::eStorageImage,
|
||||||
},
|
},
|
||||||
.binding_count = 4, // TODO: Combine cube faces to a single storage image
|
.binding_count = 7, // TODO: Combine cube faces to a single storage image
|
||||||
// some android devices only expose up to four storage
|
// some android devices only expose up to four storage
|
||||||
// slots per pipeline
|
// slots per pipeline
|
||||||
},
|
},
|
||||||
|
@ -164,7 +164,7 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
|||||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||||
|
|
||||||
// Enable the instance extensions the backend uses
|
// Enable the instance extensions the backend uses
|
||||||
auto extensions = GetInstanceExtensions(window_info.type, false);
|
auto extensions = GetInstanceExtensions(window_info.type, enable_validation);
|
||||||
|
|
||||||
// Use required platform-specific flags
|
// Use required platform-specific flags
|
||||||
auto flags = GetInstanceFlags();
|
auto flags = GetInstanceFlags();
|
||||||
@ -393,7 +393,6 @@ bool Instance::CreateDevice() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
AddExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
AddExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||||
AddExtension(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME);
|
|
||||||
timeline_semaphores = AddExtension(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
|
timeline_semaphores = AddExtension(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
|
||||||
extended_dynamic_state = AddExtension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
extended_dynamic_state = AddExtension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
push_descriptors = AddExtension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
push_descriptors = AddExtension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||||
@ -452,7 +451,7 @@ bool Instance::CreateDevice() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const u32 queue_count = graphics_queue_family_index != present_queue_family_index ? 2u : 1u;
|
const u32 queue_count = graphics_queue_family_index != present_queue_family_index ? 2u : 1u;
|
||||||
const vk::StructureChain device_chain = {
|
vk::StructureChain device_chain = {
|
||||||
vk::DeviceCreateInfo{
|
vk::DeviceCreateInfo{
|
||||||
.queueCreateInfoCount = queue_count,
|
.queueCreateInfoCount = queue_count,
|
||||||
.pQueueCreateInfos = queue_infos.data(),
|
.pQueueCreateInfos = queue_infos.data(),
|
||||||
@ -460,8 +459,7 @@ bool Instance::CreateDevice() {
|
|||||||
.ppEnabledExtensionNames = enabled_extensions.data(),
|
.ppEnabledExtensionNames = enabled_extensions.data(),
|
||||||
},
|
},
|
||||||
vk::PhysicalDeviceFeatures2{
|
vk::PhysicalDeviceFeatures2{
|
||||||
.features =
|
.features{
|
||||||
{
|
|
||||||
.robustBufferAccess = features.robustBufferAccess,
|
.robustBufferAccess = features.robustBufferAccess,
|
||||||
.geometryShader = features.geometryShader,
|
.geometryShader = features.geometryShader,
|
||||||
.dualSrcBlend = features.dualSrcBlend,
|
.dualSrcBlend = features.dualSrcBlend,
|
||||||
@ -474,10 +472,32 @@ bool Instance::CreateDevice() {
|
|||||||
.shaderClipDistance = features.shaderClipDistance,
|
.shaderClipDistance = features.shaderClipDistance,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(),
|
||||||
feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(),
|
feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(),
|
||||||
feature_chain.get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>(),
|
feature_chain.get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>(),
|
||||||
feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(),
|
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>(),
|
||||||
feature_chain.get<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>()};
|
};
|
||||||
|
|
||||||
|
if (!extended_dynamic_state) {
|
||||||
|
device_chain.unlink<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!custom_border_color) {
|
||||||
|
device_chain.unlink<vk::PhysicalDeviceCustomBorderColorFeaturesEXT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!index_type_uint8) {
|
||||||
|
device_chain.unlink<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if VK_KHR_portability_subset
|
||||||
|
const vk::StructureChain portability_chain =
|
||||||
|
physical_device.getFeatures2<vk::PhysicalDeviceFeatures2,
|
||||||
|
vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
|
||||||
|
const vk::PhysicalDevicePortabilitySubsetFeaturesKHR portability_features =
|
||||||
|
portability_chain.get<vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
|
||||||
|
triangle_fan_supported = portability_features.triangleFans;
|
||||||
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
device = physical_device.createDevice(device_chain.get());
|
device = physical_device.createDevice(device_chain.get());
|
||||||
|
@ -185,6 +185,11 @@ public:
|
|||||||
return limits.maxTexelBufferElements;
|
return limits.maxTexelBufferElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if triangle fan is an accepted primitive topology
|
||||||
|
bool IsTriangleFanSupported() const {
|
||||||
|
return triangle_fan_supported;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Returns the optimal supported usage for the requested format
|
/// Returns the optimal supported usage for the requested format
|
||||||
vk::FormatFeatureFlags GetFormatFeatures(vk::Format format);
|
vk::FormatFeatureFlags GetFormatFeatures(vk::Format format);
|
||||||
@ -222,6 +227,7 @@ private:
|
|||||||
u32 present_queue_family_index{0};
|
u32 present_queue_family_index{0};
|
||||||
u32 graphics_queue_family_index{0};
|
u32 graphics_queue_family_index{0};
|
||||||
|
|
||||||
|
bool triangle_fan_supported{true};
|
||||||
bool timeline_semaphores{};
|
bool timeline_semaphores{};
|
||||||
bool extended_dynamic_state{};
|
bool extended_dynamic_state{};
|
||||||
bool push_descriptors{};
|
bool push_descriptors{};
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
using TriangleTopology = Pica::PipelineRegs::TriangleTopology;
|
||||||
|
|
||||||
constexpr u64 VERTEX_BUFFER_SIZE = 128 * 1024 * 1024;
|
constexpr u64 VERTEX_BUFFER_SIZE = 128 * 1024 * 1024;
|
||||||
constexpr u64 TEXTURE_BUFFER_SIZE = 2 * 1024 * 1024;
|
constexpr u64 TEXTURE_BUFFER_SIZE = 2 * 1024 * 1024;
|
||||||
|
|
||||||
@ -391,8 +393,10 @@ bool RasterizerVulkan::AccelerateDrawBatchInternal(bool is_indexed) {
|
|||||||
const auto [vs_input_index_min, vs_input_index_max, vs_input_size] =
|
const auto [vs_input_index_min, vs_input_index_max, vs_input_size] =
|
||||||
AnalyzeVertexArray(is_indexed);
|
AnalyzeVertexArray(is_indexed);
|
||||||
|
|
||||||
if (vs_input_size > VERTEX_BUFFER_SIZE) {
|
if (regs.pipeline.triangle_topology == TriangleTopology::Fan &&
|
||||||
LOG_WARNING(Render_Vulkan, "Too large vertex input size {}", vs_input_size);
|
!instance.IsTriangleFanSupported()) {
|
||||||
|
LOG_DEBUG(Render_Vulkan,
|
||||||
|
"Skipping accelerated draw with unsupported triangle fan topology");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,10 +802,10 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
depth_surface);
|
depth_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int submit_threshold = 20;
|
static int submit_threshold = 40;
|
||||||
submit_threshold--;
|
submit_threshold--;
|
||||||
if (!submit_threshold) {
|
if (!submit_threshold) {
|
||||||
submit_threshold = 20;
|
submit_threshold = 40;
|
||||||
scheduler.Flush();
|
scheduler.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ void Swapchain::Create() {
|
|||||||
.queueFamilyIndexCount = queue_family_indices_count,
|
.queueFamilyIndexCount = queue_family_indices_count,
|
||||||
.pQueueFamilyIndices = queue_family_indices.data(),
|
.pQueueFamilyIndices = queue_family_indices.data(),
|
||||||
.preTransform = transform,
|
.preTransform = transform,
|
||||||
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eInherit,
|
.compositeAlpha = composite_alpha,
|
||||||
.presentMode = present_mode,
|
.presentMode = present_mode,
|
||||||
.clipped = true,
|
.clipped = true,
|
||||||
.oldSwapchain = swapchain,
|
.oldSwapchain = swapchain,
|
||||||
@ -210,6 +210,12 @@ void Swapchain::SetSurfaceProperties() {
|
|||||||
if (!(capabilities.supportedTransforms & transform)) {
|
if (!(capabilities.supportedTransforms & transform)) {
|
||||||
transform = capabilities.currentTransform;
|
transform = capabilities.currentTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Opaque is not supported everywhere.
|
||||||
|
composite_alpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
|
||||||
|
if (!(capabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::eOpaque)) {
|
||||||
|
composite_alpha = vk::CompositeAlphaFlagBitsKHR::eInherit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swapchain::Destroy() {
|
void Swapchain::Destroy() {
|
||||||
@ -237,8 +243,7 @@ void Swapchain::SetupImages() {
|
|||||||
.image = image,
|
.image = image,
|
||||||
.viewType = vk::ImageViewType::e2D,
|
.viewType = vk::ImageViewType::e2D,
|
||||||
.format = surface_format.format,
|
.format = surface_format.format,
|
||||||
.subresourceRange =
|
.subresourceRange{
|
||||||
{
|
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
.baseMipLevel = 0,
|
.baseMipLevel = 0,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
|
@ -94,6 +94,7 @@ private:
|
|||||||
vk::PresentModeKHR present_mode;
|
vk::PresentModeKHR present_mode;
|
||||||
vk::Extent2D extent;
|
vk::Extent2D extent;
|
||||||
vk::SurfaceTransformFlagBitsKHR transform;
|
vk::SurfaceTransformFlagBitsKHR transform;
|
||||||
|
vk::CompositeAlphaFlagBitsKHR composite_alpha;
|
||||||
std::vector<vk::Image> images;
|
std::vector<vk::Image> images;
|
||||||
std::vector<vk::ImageView> image_views;
|
std::vector<vk::ImageView> image_views;
|
||||||
std::vector<vk::Framebuffer> framebuffers;
|
std::vector<vk::Framebuffer> framebuffers;
|
||||||
|
Reference in New Issue
Block a user