Implement vk_android_native_buffer (basic)
This is the minimum amount of code to get a triangle
on an Android device using Swiftshader
Bug: b/122837237
Change-Id: I8d2af6c104d70650c8750c9dd54d5be32ded0a39
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30828
Tested-by: Hernan Liatis <hliatis@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Android.bp b/src/Android.bp
index b770a96..de2a228 100644
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -647,16 +647,17 @@
],
srcs: [
- "Common/CPUID.cpp",
- "Common/Configurator.cpp",
- "Common/Half.cpp",
- "Common/Math.cpp",
- "Common/Memory.cpp",
- "Common/Resource.cpp",
- "Common/Socket.cpp",
- "Common/Thread.cpp",
- "Common/Timer.cpp",
- "Common/DebugAndroid.cpp",
+ "System/CPUID.cpp",
+ "System/Configurator.cpp",
+ "System/Half.cpp",
+ "System/Math.cpp",
+ "System/Memory.cpp",
+ "System/Resource.cpp",
+ "System/Socket.cpp",
+ "System/Thread.cpp",
+ "System/Timer.cpp",
+ "System/DebugAndroid.cpp",
+ "System/GrallocAndroid.cpp",
"Device/*.cpp",
"Pipeline/*.cpp",
"Vulkan/*.cpp",
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 1b91fea..5334dbd 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -48,7 +48,7 @@
#ifdef __ANDROID__
#include <vulkan/vk_android_native_buffer.h>
-#include <hardware/gralloc1.h>
+#include "System/GrallocAndroid.hpp"
#endif
#include "WSI/VkSwapchainKHR.hpp"
@@ -56,6 +56,7 @@
#include <algorithm>
#include <cstring>
#include <string>
+#include <map>
namespace
{
@@ -904,14 +905,56 @@
vk::destroy(bufferView, pAllocator);
}
+#ifdef __ANDROID__
+struct BackingMemory {
+ buffer_handle_t nativeHandle;
+ int stride;
+ VkDeviceMemory imageMemory;
+ VkSwapchainImageUsageFlagsANDROID androidUsage;
+};
+
+static std::map<VkImage, BackingMemory> androidSwapchainMap;
+#endif
+
VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage)
{
TRACE("(VkDevice device = %p, const VkImageCreateInfo* pCreateInfo = %p, const VkAllocationCallbacks* pAllocator = %p, VkImage* pImage = %p)",
device, pCreateInfo, pAllocator, pImage);
- if(pCreateInfo->pNext)
+ const VkBaseInStructure* extensionCreateInfo = reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext);
+
+#ifdef __ANDROID__
+ BackingMemory backmem;
+ bool swapchainImage = false;
+#endif
+
+ while(extensionCreateInfo)
{
- UNIMPLEMENTED("pCreateInfo->pNext");
+ switch((long)(extensionCreateInfo->sType))
+ {
+#ifdef __ANDROID__
+ case VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID:
+ {
+ const VkSwapchainImageCreateInfoANDROID* swapImageCreateInfo = reinterpret_cast<const VkSwapchainImageCreateInfoANDROID*>(extensionCreateInfo);
+ backmem.androidUsage = swapImageCreateInfo->usage;
+ }
+ break;
+ case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID:
+ {
+ const VkNativeBufferANDROID* nativeBufferInfo = reinterpret_cast<const VkNativeBufferANDROID*>(extensionCreateInfo);
+ backmem.nativeHandle = nativeBufferInfo->handle;
+ backmem.stride = nativeBufferInfo->stride;
+ swapchainImage = true
+ }
+ break;
+#endif
+ 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"); // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here.
+ break;
+ }
+
+ extensionCreateInfo = extensionCreateInfo->pNext;
}
vk::Image::CreateInfo imageCreateInfo =
@@ -920,7 +963,36 @@
device
};
- return vk::Image::Create(pAllocator, &imageCreateInfo, pImage);
+ VkResult result = vk::Image::Create(pAllocator, &imageCreateInfo, pImage);
+
+#ifdef __ANDROID__
+ if (swapchainImage)
+ {
+ if (result != VK_SUCCESS)
+ {
+ return result;
+ }
+
+ VkMemoryRequirements memRequirements = vk::Cast(*pImage)->getMemoryRequirements();
+
+ VkMemoryAllocateInfo allocInfo = {};
+ allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocInfo.allocationSize = memRequirements.size;
+ allocInfo.memoryTypeIndex = 0;
+
+ result = vkAllocateMemory(device, &allocInfo, nullptr, &backmem.imageMemory);
+ if(result != VK_SUCCESS)
+ {
+ return result;
+ }
+
+ vkBindImageMemory(device, *pImage, backmem.imageMemory, 0);
+
+ androidSwapchainMap[*pImage] = backmem;
+ }
+#endif
+
+ return result;
}
VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator)
@@ -2575,7 +2647,7 @@
VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage)
{
- TRACE("(VkDevice device = 0x%X, VkFormat format = 0x%X, VkImageUsageFlags imageUsage = 0x%X, VkSwapchainImageUsageFlagsANDROID swapchainUsage = 0x%X, uint64_t* grallocConsumerUsage = 0x%X, uin64_t* grallocProducerUsage = 0x%X)",
+ TRACE("(VkDevice device = %p, VkFormat format = %d, VkImageUsageFlags imageUsage = %d, VkSwapchainImageUsageFlagsANDROID swapchainUsage = %d, uint64_t* grallocConsumerUsage = %p, uin64_t* grallocProducerUsage = %p)",
device, format, imageUsage, swapchainUsage, grallocConsumerUsage, grallocProducerUsage);
*grallocConsumerUsage = 0;
@@ -2586,7 +2658,7 @@
VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage)
{
- TRACE("(VkDevice device = 0x%X, VkFormat format = 0x%X, VkImageUsageFlags imageUsage = 0x%X, int* grallocUsage = 0x%X)",
+ TRACE("(VkDevice device = %p, VkFormat format = %d, VkImageUsageFlags imageUsage = %d, int* grallocUsage = %p)",
device, format, imageUsage, grallocUsage);
return VK_SUCCESS;
@@ -2594,7 +2666,7 @@
VKAPI_ATTR VkResult VKAPI_CALL vkAcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence)
{
- TRACE("(VkDevice device = 0x%X, VkImage image = 0x%X, int nativeFenceFd = 0x%X, VkSemaphore semaphore = 0x%X, VkFence fence = 0x%X)",
+ TRACE("(VkDevice device = %p, VkImage image = %p, int nativeFenceFd = %d, VkSemaphore semaphore = %p, VkFence fence = %p)",
device, image, nativeFenceFd, semaphore, fence);
return VK_SUCCESS;
@@ -2602,9 +2674,31 @@
VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd)
{
- TRACE("(VkQueue queue = 0x%X, uint32_t waitSemaphoreCount = 0x%X, const VkSemaphore* pWaitSemaphores = 0x%X, VkImage image = 0x%X, int* pNativeFenceFd = 0x%X)",
+ TRACE("(VkQueue queue = %p, uint32_t waitSemaphoreCount = %d, const VkSemaphore* pWaitSemaphores = %p, VkImage image = %p, int* pNativeFenceFd = %p)",
queue, waitSemaphoreCount, pWaitSemaphores, image, pNativeFenceFd);
+ GrallocModule* grallocMod = GrallocModule::getInstance();
+ void* nativeBuffer;
+
+ auto it = androidSwapchainMap.find(image);
+
+ if (it == androidSwapchainMap.end())
+ ABORT("ANDROID: Swapchain image not found");
+
+ BackingMemory backmem = it->second;
+
+ VkExtent3D extent = vk::Cast(image)->getMipLevelExtent(0);
+ grallocMod->lock(backmem.nativeHandle, GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, extent.width, extent.height, &nativeBuffer);
+
+ char* buffer = static_cast<char*>(vk::Cast(backmem.imageMemory)->getOffsetPointer(0));
+ int imageRowBytes = vk::Cast(image)->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
+ int colorBytes = vk::Cast(image)->getFormat().bytes();
+
+ for(int i = 0; i < extent.height; i++)
+ {
+ memcpy((void*)((char*)nativeBuffer + (i * backmem.stride * colorBytes)), buffer + (i * imageRowBytes), imageRowBytes);
+ }
+
return VK_SUCCESS;
}
#endif // __ANDROID__