diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 9c12ae1f5..72ed345f2 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -9,6 +9,41 @@ namespace dxvk { + VkPrimitiveTopology determineGsInputTopology( + VkPrimitiveTopology shader, + VkPrimitiveTopology state) { + switch (state) { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; + + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + if (shader == VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY) + return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; + [[fallthrough]]; + + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + if (shader == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY) + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY; + [[fallthrough]]; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + default: + Logger::err(str::format("Unhandled primitive topology ", state)); + return VK_PRIMITIVE_TOPOLOGY_MAX_ENUM; + } + } + + DxvkGraphicsPipelineVertexInputState::DxvkGraphicsPipelineVertexInputState() { } @@ -836,6 +871,13 @@ namespace dxvk { } info.undefinedInputs = (providedInputs & consumedInputs) ^ consumedInputs; + + // Fix up input topology for geometry shaders as necessary + if (shaderInfo.stage == VK_SHADER_STAGE_GEOMETRY_BIT) { + VkPrimitiveTopology iaTopology = shaders.tes ? shaders.tes->info().outputTopology : state.ia.primitiveTopology(); + info.inputTopology = determineGsInputTopology(shaderInfo.inputTopology, iaTopology); + } + return info; } @@ -1190,6 +1232,16 @@ namespace dxvk { if ((vsInputMask & ilAttributeMask) != vsInputMask) return false; + if (m_shaders.gs != nullptr) { + // If the geometry shader's input topology is not compatible with + // the topology set to the pipeline, we need to patch the GS. + VkPrimitiveTopology iaTopology = m_shaders.tes ? m_shaders.tes->info().outputTopology : state.ia.primitiveTopology(); + VkPrimitiveTopology gsTopology = m_shaders.gs->info().inputTopology; + + if (determineGsInputTopology(gsTopology, iaTopology) != gsTopology) + return false; + } + if (m_shaders.tcs != nullptr) { // If tessellation shaders are present, the input patch // vertex count must match the shader's definition.