diff --git a/src/video_core/renderer_vulkan/vk_descriptor_manager.cpp b/src/video_core/renderer_vulkan/vk_descriptor_manager.cpp index 608d60884..55bdc6232 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_manager.cpp @@ -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 }, diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 07f639c3f..fb05dae04 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -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(), feature_chain.get(), feature_chain.get(), - feature_chain.get(), - feature_chain.get()}; + feature_chain.get(), + }; + + if (!extended_dynamic_state) { + device_chain.unlink(); + } + + if (!custom_border_color) { + device_chain.unlink(); + } + + if (!index_type_uint8) { + device_chain.unlink(); + } + +#if VK_KHR_portability_subset + const vk::StructureChain portability_chain = + physical_device.getFeatures2(); + const vk::PhysicalDevicePortabilitySubsetFeaturesKHR portability_features = + portability_chain.get(); + triangle_fan_supported = portability_features.triangleFans; +#endif try { device = physical_device.createDevice(device_chain.get()); diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index fda6a32c1..635b605f2 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -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{}; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 1e570c382..977054319 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -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(); } diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index b590ae152..d4395ff4e 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -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)); diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index 75db526be..b0dadc0ca 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -94,6 +94,7 @@ private: vk::PresentModeKHR present_mode; vk::Extent2D extent; vk::SurfaceTransformFlagBitsKHR transform; + vk::CompositeAlphaFlagBitsKHR composite_alpha; std::vector images; std::vector image_views; std::vector framebuffers;