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,
|
||||
},
|
||||
.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
|
||||
// slots per pipeline
|
||||
},
|
||||
|
@ -164,7 +164,7 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||
|
||||
// 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
|
||||
auto flags = GetInstanceFlags();
|
||||
@ -393,7 +393,6 @@ bool Instance::CreateDevice() {
|
||||
};
|
||||
|
||||
AddExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
AddExtension(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME);
|
||||
timeline_semaphores = AddExtension(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
|
||||
extended_dynamic_state = AddExtension(VK_EXT_EXTENDED_DYNAMIC_STATE_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 vk::StructureChain device_chain = {
|
||||
vk::StructureChain device_chain = {
|
||||
vk::DeviceCreateInfo{
|
||||
.queueCreateInfoCount = queue_count,
|
||||
.pQueueCreateInfos = queue_infos.data(),
|
||||
@ -460,24 +459,45 @@ bool Instance::CreateDevice() {
|
||||
.ppEnabledExtensionNames = enabled_extensions.data(),
|
||||
},
|
||||
vk::PhysicalDeviceFeatures2{
|
||||
.features =
|
||||
{
|
||||
.robustBufferAccess = features.robustBufferAccess,
|
||||
.geometryShader = features.geometryShader,
|
||||
.dualSrcBlend = features.dualSrcBlend,
|
||||
.logicOp = features.logicOp,
|
||||
.depthClamp = features.depthClamp,
|
||||
.largePoints = features.largePoints,
|
||||
.samplerAnisotropy = features.samplerAnisotropy,
|
||||
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
|
||||
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
|
||||
.shaderClipDistance = features.shaderClipDistance,
|
||||
},
|
||||
.features{
|
||||
.robustBufferAccess = features.robustBufferAccess,
|
||||
.geometryShader = features.geometryShader,
|
||||
.dualSrcBlend = features.dualSrcBlend,
|
||||
.logicOp = features.logicOp,
|
||||
.depthClamp = features.depthClamp,
|
||||
.largePoints = features.largePoints,
|
||||
.samplerAnisotropy = features.samplerAnisotropy,
|
||||
.fragmentStoresAndAtomics = features.fragmentStoresAndAtomics,
|
||||
.shaderStorageImageMultisample = features.shaderStorageImageMultisample,
|
||||
.shaderClipDistance = features.shaderClipDistance,
|
||||
},
|
||||
},
|
||||
feature_chain.get<vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR>(),
|
||||
feature_chain.get<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>(),
|
||||
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 {
|
||||
device = physical_device.createDevice(device_chain.get());
|
||||
|
@ -185,6 +185,11 @@ public:
|
||||
return limits.maxTexelBufferElements;
|
||||
}
|
||||
|
||||
/// Returns true if triangle fan is an accepted primitive topology
|
||||
bool IsTriangleFanSupported() const {
|
||||
return triangle_fan_supported;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Returns the optimal supported usage for the requested format
|
||||
vk::FormatFeatureFlags GetFormatFeatures(vk::Format format);
|
||||
@ -222,6 +227,7 @@ private:
|
||||
u32 present_queue_family_index{0};
|
||||
u32 graphics_queue_family_index{0};
|
||||
|
||||
bool triangle_fan_supported{true};
|
||||
bool timeline_semaphores{};
|
||||
bool extended_dynamic_state{};
|
||||
bool push_descriptors{};
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
using TriangleTopology = Pica::PipelineRegs::TriangleTopology;
|
||||
|
||||
constexpr u64 VERTEX_BUFFER_SIZE = 128 * 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] =
|
||||
AnalyzeVertexArray(is_indexed);
|
||||
|
||||
if (vs_input_size > VERTEX_BUFFER_SIZE) {
|
||||
LOG_WARNING(Render_Vulkan, "Too large vertex input size {}", vs_input_size);
|
||||
if (regs.pipeline.triangle_topology == TriangleTopology::Fan &&
|
||||
!instance.IsTriangleFanSupported()) {
|
||||
LOG_DEBUG(Render_Vulkan,
|
||||
"Skipping accelerated draw with unsupported triangle fan topology");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -798,10 +802,10 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
||||
depth_surface);
|
||||
}
|
||||
|
||||
static int submit_threshold = 20;
|
||||
static int submit_threshold = 40;
|
||||
submit_threshold--;
|
||||
if (!submit_threshold) {
|
||||
submit_threshold = 20;
|
||||
submit_threshold = 40;
|
||||
scheduler.Flush();
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ void Swapchain::Create() {
|
||||
.queueFamilyIndexCount = queue_family_indices_count,
|
||||
.pQueueFamilyIndices = queue_family_indices.data(),
|
||||
.preTransform = transform,
|
||||
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eInherit,
|
||||
.compositeAlpha = composite_alpha,
|
||||
.presentMode = present_mode,
|
||||
.clipped = true,
|
||||
.oldSwapchain = swapchain,
|
||||
@ -210,6 +210,12 @@ void Swapchain::SetSurfaceProperties() {
|
||||
if (!(capabilities.supportedTransforms & transform)) {
|
||||
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() {
|
||||
@ -237,14 +243,13 @@ void Swapchain::SetupImages() {
|
||||
.image = image,
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = surface_format.format,
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
image_views.push_back(device.createImageView(view_info));
|
||||
|
@ -94,6 +94,7 @@ private:
|
||||
vk::PresentModeKHR present_mode;
|
||||
vk::Extent2D extent;
|
||||
vk::SurfaceTransformFlagBitsKHR transform;
|
||||
vk::CompositeAlphaFlagBitsKHR composite_alpha;
|
||||
std::vector<vk::Image> images;
|
||||
std::vector<vk::ImageView> image_views;
|
||||
std::vector<vk::Framebuffer> framebuffers;
|
||||
|
Reference in New Issue
Block a user