diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index 21459e8a8a..e484c27dac 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -72,6 +72,14 @@ bool ObjectCache::Initialize() return true; } +static bool IsStripPrimitiveTopology(VkPrimitiveTopology topology) +{ + return topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP || + topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP || + topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY || + topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; +} + static VkPipelineRasterizationStateCreateInfo GetVulkanRasterizationState(const RasterizationState& state) { @@ -185,9 +193,20 @@ VkPipeline ObjectCache::CreatePipeline(const PipelineInfo& info) nullptr, // const void* pNext 0, // VkPipelineInputAssemblyStateCreateFlags flags info.primitive_topology, // VkPrimitiveTopology topology - VK_TRUE // VkBool32 primitiveRestartEnable + VK_FALSE // VkBool32 primitiveRestartEnable }; + // See Vulkan spec, section 19: + // If topology is VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, + // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, + // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY or VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, + // primitiveRestartEnable must be VK_FALSE + if (g_ActiveConfig.backend_info.bSupportsPrimitiveRestart && + IsStripPrimitiveTopology(info.primitive_topology)) + { + input_assembly_state.primitiveRestartEnable = VK_TRUE; + } + // Shaders to stages VkPipelineShaderStageCreateInfo shader_stages[3]; uint32_t num_shader_stages = 0; diff --git a/Source/Core/VideoBackends/Vulkan/VertexManager.cpp b/Source/Core/VideoBackends/Vulkan/VertexManager.cpp index 9a5e821e19..a1d72f3011 100644 --- a/Source/Core/VideoBackends/Vulkan/VertexManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/VertexManager.cpp @@ -153,7 +153,10 @@ void VertexManager::vFlush() break; case PRIMITIVE_TRIANGLES: - StateTracker::GetInstance()->SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); + StateTracker::GetInstance()->SetPrimitiveTopology( + g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP : + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); g_renderer->SetGenerationMode(); break; } diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index a7d1b628fb..7dc809e6b2 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -276,6 +276,11 @@ void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalD // Depth clamping implies shaderClipDistance and depthClamp config->backend_info.bSupportsDepthClamp = (features.depthClamp == VK_TRUE && features.shaderClipDistance == VK_TRUE); + + // Our usage of primitive restart appears to be broken on AMD's binary drivers. + // Seems to be fine on GCN Gen 1-2, unconfirmed on GCN Gen 3, causes driver resets on GCN Gen 4. + if (DriverDetails::HasBug(DriverDetails::BUG_PRIMITIVE_RESTART)) + config->backend_info.bSupportsPrimitiveRestart = false; } void VulkanContext::PopulateBackendInfoMultisampleModes( diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp index 8d3c4715fb..072f7b69de 100644 --- a/Source/Core/VideoCommon/DriverDetails.cpp +++ b/Source/Core/VideoCommon/DriverDetails.cpp @@ -90,6 +90,8 @@ static BugInfo m_known_bugs[] = { BUG_BROKEN_DUAL_SOURCE_BLENDING, -1.0, -1.0, true}, {API_OPENGL, OS_OSX, VENDOR_INTEL, DRIVER_INTEL, Family::UNKNOWN, BUG_BROKEN_DUAL_SOURCE_BLENDING, -1.0, -1.0, true}, + {API_VULKAN, OS_ALL, VENDOR_ATI, DRIVER_ATI, Family::UNKNOWN, BUG_PRIMITIVE_RESTART, -1.0, -1.0, + true}, }; static std::map m_bugs;