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.