Implement VK_EXT_headless_surface

This implements the extension defined here:
https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_EXT_headless_surface.html

This extension is useful for tests/benchmarks as it provides a way to
create a platform-agnostic Surface with Swapchain, etc., instead of
having to create an non-visible framebuffer.

Bug: b/176981107
Change-Id: Iad1e55ed7a4e32cebf7577d9d88a9aed4b6f7a20
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51589
Tested-by: Antonio Maiorano <amaiorano@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index ebc3220..0edcfcf 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -147,6 +147,7 @@
 	MAKE_VULKAN_INSTANCE_ENTRY(vkCreateWin32SurfaceKHR),
 	MAKE_VULKAN_INSTANCE_ENTRY(vkGetPhysicalDeviceWin32PresentationSupportKHR),
 #endif
+	MAKE_VULKAN_INSTANCE_ENTRY(vkCreateHeadlessSurfaceEXT),
 };
 #undef MAKE_VULKAN_INSTANCE_ENTRY
 
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index d4dbc89..36d8a21 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -73,6 +73,8 @@
 #	include "WSI/Win32SurfaceKHR.hpp"
 #endif
 
+#include "WSI/HeadlessSurfaceKHR.hpp"
+
 #ifdef __ANDROID__
 #	include "commit.h"
 #	include "System/GrallocAndroid.hpp"
@@ -3740,6 +3742,14 @@
 }
 #endif
 
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface)
+{
+	TRACE("(VkInstance instance = %p, VkHeadlessSurfaceCreateInfoEXT* pCreateInfo = %p, VkAllocationCallbacks* pAllocator = %p, VkSurface* pSurface = %p)",
+	      instance, pCreateInfo, pAllocator, pSurface);
+
+	return vk::HeadlessSurfaceKHR::Create(pAllocator, pCreateInfo, pSurface);
+}
+
 #ifndef __ANDROID__
 VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator)
 {
diff --git a/src/Vulkan/vk_swiftshader.def b/src/Vulkan/vk_swiftshader.def
index 464bb59..77fb8c6 100644
--- a/src/Vulkan/vk_swiftshader.def
+++ b/src/Vulkan/vk_swiftshader.def
@@ -231,3 +231,5 @@
 	vkGetPhysicalDeviceWin32PresentationSupportKHR

 	; VK_EXT_host_query_reset

 	vkResetQueryPool

+	; VK_EXT_headless_surface

+	vkCreateHeadlessSurfaceEXT

diff --git a/src/Vulkan/vk_swiftshader.lds b/src/Vulkan/vk_swiftshader.lds
index 1e43950..768114e 100644
--- a/src/Vulkan/vk_swiftshader.lds
+++ b/src/Vulkan/vk_swiftshader.lds
@@ -228,6 +228,8 @@
 	vkGetPhysicalDeviceSurfacePresentModesKHR;
 	# VK_EXT_host_query_reset
 	vkResetQueryPool;
+	# VK_EXT_headless_surface
+	vkCreateHeadlessSurfaceEXT;
 
 	# Android HAL module info object
 	HMI;
diff --git a/src/WSI/BUILD.gn b/src/WSI/BUILD.gn
index 2116b63..248ba31 100644
--- a/src/WSI/BUILD.gn
+++ b/src/WSI/BUILD.gn
@@ -25,6 +25,8 @@
 
 swiftshader_source_set("WSI") {
   sources = [
+    "HeadlessSurfaceKHR.cpp",
+    "HeadlessSurfaceKHR.hpp",
     "VkSurfaceKHR.cpp",
     "VkSurfaceKHR.hpp",
     "VkSwapchainKHR.cpp",
diff --git a/src/WSI/CMakeLists.txt b/src/WSI/CMakeLists.txt
index 8ba95d5..84f5d80 100644
--- a/src/WSI/CMakeLists.txt
+++ b/src/WSI/CMakeLists.txt
@@ -18,6 +18,8 @@
 )
 
 set(WSI_SRC_FILES
+    HeadlessSurfaceKHR.cpp
+    HeadlessSurfaceKHR.hpp
     VkSurfaceKHR.cpp
     VkSurfaceKHR.hpp
     VkSwapchainKHR.cpp
diff --git a/src/WSI/HeadlessSurfaceKHR.cpp b/src/WSI/HeadlessSurfaceKHR.cpp
new file mode 100644
index 0000000..41a298b
--- /dev/null
+++ b/src/WSI/HeadlessSurfaceKHR.cpp
@@ -0,0 +1,57 @@
+// Copyright 2021 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "HeadlessSurfaceKHR.hpp"
+
+namespace vk {
+
+HeadlessSurfaceKHR::HeadlessSurfaceKHR(const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo, void *mem)
+{
+}
+
+size_t HeadlessSurfaceKHR::ComputeRequiredAllocationSize(const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo)
+{
+	return 0;
+}
+
+void HeadlessSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
+{
+}
+
+void HeadlessSurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const
+{
+	SurfaceKHR::getSurfaceCapabilities(pSurfaceCapabilities);
+	// We could return {0,0} here, but as this type of surface is useful for testing, we return a more
+	// common size here so that buffers like Swapchain images get created with reasonable sizes, and
+	// so that drawing actually exercises common code paths.
+	VkExtent2D extent{ 1280, 720 };
+	pSurfaceCapabilities->currentExtent = extent;
+	pSurfaceCapabilities->minImageExtent = extent;
+	pSurfaceCapabilities->maxImageExtent = extent;
+}
+
+void HeadlessSurfaceKHR::attachImage(PresentImage *image)
+{
+}
+
+void HeadlessSurfaceKHR::detachImage(PresentImage *image)
+{
+}
+
+VkResult HeadlessSurfaceKHR::present(PresentImage *image)
+{
+	return VK_SUCCESS;
+}
+
+}  // namespace vk
\ No newline at end of file
diff --git a/src/WSI/HeadlessSurfaceKHR.hpp b/src/WSI/HeadlessSurfaceKHR.hpp
new file mode 100644
index 0000000..b2e5bd7
--- /dev/null
+++ b/src/WSI/HeadlessSurfaceKHR.hpp
@@ -0,0 +1,37 @@
+// Copyright 2021 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SWIFTSHADER_HEADLESSSURFACEKHR_HPP
+#define SWIFTSHADER_HEADLESSSURFACEKHR_HPP
+
+#include "VkSurfaceKHR.hpp"
+
+namespace vk {
+
+class HeadlessSurfaceKHR : public SurfaceKHR, public ObjectBase<HeadlessSurfaceKHR, VkSurfaceKHR>
+{
+public:
+	HeadlessSurfaceKHR(const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo, void *mem);
+
+	static size_t ComputeRequiredAllocationSize(const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo);
+
+	void destroySurface(const VkAllocationCallbacks *pAllocator) override;
+	void getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const override;
+	void attachImage(PresentImage *image) override;
+	void detachImage(PresentImage *image) override;
+	VkResult present(PresentImage *image) override;
+};
+
+}  // namespace vk
+#endif  //SWIFTSHADER_HEADLESSSURFACEKHR_HPP