Enable support for Bresenham lines

Bresenham lines are required by ANGLE in order to support emulation
of OpenGL ES style lines on top of SwiftShader Vulkan.

Bug: b/139800520
Change-Id: I8b77775af836a238d309cc19b495b61d2c3a3487
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/37428
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index 34a22a7..182c8b3 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -110,6 +110,7 @@
 
 		cullMode = VK_CULL_MODE_FRONT_BIT;
 		frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+		lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
 
 		depthBias = 0.0f;
 		slopeDepthBias = 0.0f;
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index 2736a9e..df57ef9 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -97,6 +97,7 @@
 		VkCullModeFlags cullMode;
 		VkFrontFace frontFace;
 		VkPolygonMode polygonMode;
+		VkLineRasterizationModeEXT lineRasterizationMode;
 
 		float depthBias;
 		float slopeDepthBias;
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 2f137b8..b5c0a47 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -261,6 +261,7 @@
 		draw->numBatches = (count + draw->numPrimitivesPerBatch - 1) / draw->numPrimitivesPerBatch;
 		draw->topology = context->topology;
 		draw->indexType = indexType;
+		draw->lineRasterizationMode = context->lineRasterizationMode;
 
 		draw->vertexRoutine = vertexRoutine;
 		draw->setupRoutine = setupRoutine;
@@ -813,7 +814,15 @@
 			return false;
 		}
 
-		if(true)   // Rectangle centered on the line segment
+		// TODO(b/142965928): Bresenham lines should render the same with or without
+		//                    multisampling, which will require a special case in the
+		//                    code when multisampling is on. For now, we just use
+		//                    rectangular lines when multisampling is enabled.
+
+		// We use rectangular lines for non Bresenham lines and
+		// for Bresenham lines when multiSampling is enabled
+		if((draw.setupState.multiSample > 1) ||
+		   (draw.lineRasterizationMode != VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT))   // Rectangle centered on the line segment
 		{
 			float4 P[4];
 			int C[4];
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index 11a58ea..02bf74c 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -151,6 +151,7 @@
 
 		VkPrimitiveTopology topology;
 		VkIndexType indexType;
+		VkLineRasterizationModeEXT lineRasterizationMode;
 
 		std::shared_ptr<Routine> vertexRoutine;
 		std::shared_ptr<Routine> setupRoutine;
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 0d8537d..7ae4b6c 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -134,6 +134,16 @@
 	features->shaderDrawParameters = VK_FALSE;
 }
 
+void PhysicalDevice::getFeatures(VkPhysicalDeviceLineRasterizationFeaturesEXT* features) const
+{
+	features->rectangularLines = VK_TRUE;
+    features->bresenhamLines = VK_TRUE;
+    features->smoothLines = VK_FALSE;
+    features->stippledRectangularLines = VK_FALSE;
+    features->stippledBresenhamLines = VK_FALSE;
+    features->stippledSmoothLines = VK_FALSE;
+}
+
 VkSampleCountFlags PhysicalDevice::getSampleCounts() const
 {
 	return VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
@@ -379,6 +389,11 @@
 	properties->conformanceVersion = {1, 1, 3, 3};
 }
 
+void PhysicalDevice::getProperties(VkPhysicalDeviceLineRasterizationPropertiesEXT* properties) const
+{
+	properties->lineSubPixelPrecisionBits = vk::SUBPIXEL_PRECISION_BITS;
+}
+
 bool PhysicalDevice::hasFeatures(const VkPhysicalDeviceFeatures& requestedFeatures) const
 {
 	const VkPhysicalDeviceFeatures& supportedFeatures = getFeatures();
diff --git a/src/Vulkan/VkPhysicalDevice.hpp b/src/Vulkan/VkPhysicalDevice.hpp
index fb6abce..858cb37 100644
--- a/src/Vulkan/VkPhysicalDevice.hpp
+++ b/src/Vulkan/VkPhysicalDevice.hpp
@@ -43,6 +43,7 @@
 	void getFeatures(VkPhysicalDeviceMultiviewFeatures* features) const;
 	void getFeatures(VkPhysicalDeviceProtectedMemoryFeatures* features) const;
 	void getFeatures(VkPhysicalDeviceShaderDrawParameterFeatures* features) const;
+	void getFeatures(VkPhysicalDeviceLineRasterizationFeaturesEXT* features) const;
 	bool hasFeatures(const VkPhysicalDeviceFeatures& requestedFeatures) const;
 
 	const VkPhysicalDeviceProperties& getProperties() const;
@@ -61,6 +62,7 @@
 	void getProperties(const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) const;
 	void getProperties(const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) const;
 	void getProperties(VkPhysicalDeviceDriverPropertiesKHR* properties) const;
+	void getProperties(VkPhysicalDeviceLineRasterizationPropertiesEXT* properties) const;
 
 	void getFormatProperties(Format format, VkFormatProperties* pFormatProperties) const;
 	void getImageFormatProperties(Format format, VkImageType type, VkImageTiling tiling,
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index ebee9f2..a6038cb 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -397,6 +397,25 @@
 	context.depthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasConstantFactor : 0.0f;
 	context.slopeDepthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasSlopeFactor : 0.0f;
 
+	const VkBaseInStructure* extensionCreateInfo = reinterpret_cast<const VkBaseInStructure*>(rasterizationState->pNext);
+	while(extensionCreateInfo)
+	{
+		switch(extensionCreateInfo->sType)
+		{
+		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT:
+		{
+			const VkPipelineRasterizationLineStateCreateInfoEXT* lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT*>(extensionCreateInfo);
+			context.lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode;
+		}
+		break;
+		default:
+			UNIMPLEMENTED("extensionCreateInfo->sType");
+			break;
+		}
+
+		extensionCreateInfo = extensionCreateInfo->pNext;
+	}
+
 	const VkPipelineMultisampleStateCreateInfo* multisampleState = pCreateInfo->pMultisampleState;
 	if(multisampleState)
 	{
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 3402c3a..fa6a6a9 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -217,6 +217,8 @@
 	// Only 1.1 core version of this is supported. The extension has additional requirements
 	//{ VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME, VK_KHR_VARIABLE_POINTERS_SPEC_VERSION },
 	{ VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION },
+	// The following extension is only used to add support for Bresenham lines
+	{ VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, VK_EXT_LINE_RASTERIZATION_SPEC_VERSION },
 #ifndef __ANDROID__
 	// We fully support the KHR_swapchain v70 additions, so just track the spec version.
 	{ VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_SPEC_VERSION },
@@ -583,6 +585,18 @@
 				}
 			}
 			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT:
+			{
+				const VkPhysicalDeviceLineRasterizationFeaturesEXT* lineRasterizationFeatures = reinterpret_cast<const VkPhysicalDeviceLineRasterizationFeaturesEXT*>(extensionCreateInfo);
+				if((lineRasterizationFeatures->smoothLines == VK_TRUE) ||
+				   (lineRasterizationFeatures->stippledBresenhamLines == VK_TRUE) ||
+				   (lineRasterizationFeatures->stippledRectangularLines == VK_TRUE) ||
+				   (lineRasterizationFeatures->stippledSmoothLines == VK_TRUE))
+				{
+					return VK_ERROR_FEATURE_NOT_PRESENT;
+				}
+			}
+			break;
 		default:
 			// "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]"
 			UNIMPLEMENTED("extensionCreateInfo->sType %d", int(extensionCreateInfo->sType));   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
@@ -2387,6 +2401,12 @@
 				vk::Cast(physicalDevice)->getFeatures(&features);
 			}
 			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT:
+			{
+				auto& features = *reinterpret_cast<VkPhysicalDeviceLineRasterizationFeaturesEXT*>(extensionFeatures);
+				vk::Cast(physicalDevice)->getFeatures(&features);
+			}
+			break;
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT:
 			ASSERT(!HasExtensionProperty(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME, deviceExtensionProperties,
 										 sizeof(deviceExtensionProperties) / sizeof(deviceExtensionProperties[0])));
@@ -2477,6 +2497,12 @@
 			}
 			break;
 #endif
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT:
+			{
+				auto& properties = *reinterpret_cast<VkPhysicalDeviceLineRasterizationPropertiesEXT*>(extensionProperties);
+				vk::Cast(physicalDevice)->getProperties(&properties);
+			}
+			break;
 		default:
 			// "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]"
 			UNIMPLEMENTED("extensionProperties->sType");   // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.