Commit 52445956 by Alexis Hetu Committed by Alexis Hétu

Avoid sync issues by removing global android swapchain map

Moved some functionality from libVulkan.cpp to VkImage.cpp in order to be able to remove the global androidSwapchainMap which may have been causing sync issues. I tried to make as much code as possible compile on desktop so that we have a better chance of detecting if a desktop related change breaks Android specific code. Bug: b/143902189 Change-Id: Ie9e17a77c2a1705b3194ebd67adeb1a3c0e6213f Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/37828 Presubmit-Ready: Alexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 414f99e0
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
#include "Device/ETC_Decoder.hpp" #include "Device/ETC_Decoder.hpp"
#include <cstring> #include <cstring>
#ifdef __ANDROID__
#include "System/GrallocAndroid.hpp"
#endif
namespace namespace
{ {
ETC_Decoder::InputType GetInputType(const vk::Format& format) ETC_Decoder::InputType GetInputType(const vk::Format& format)
...@@ -107,6 +111,47 @@ void Image::bind(DeviceMemory* pDeviceMemory, VkDeviceSize pMemoryOffset) ...@@ -107,6 +111,47 @@ void Image::bind(DeviceMemory* pDeviceMemory, VkDeviceSize pMemoryOffset)
} }
} }
#ifdef __ANDROID__
VkResult Image::prepareForExternalUseANDROID() const
{
void* nativeBuffer = nullptr;
VkExtent3D extent = getMipLevelExtent(VK_IMAGE_ASPECT_COLOR_BIT, 0);
if(GrallocModule::getInstance()->lock(backingMemory.nativeHandle, GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, extent.width, extent.height, &nativeBuffer) != 0)
{
return VK_ERROR_OUT_OF_DATE_KHR;
}
if(!nativeBuffer)
{
return VK_ERROR_OUT_OF_DATE_KHR;
}
int imageRowBytes = rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
int bufferRowBytes = backingMemory.stride * getFormat().bytes();
ASSERT(imageRowBytes <= bufferRowBytes);
uint8_t* srcBuffer = static_cast<uint8_t*>(deviceMemory->getOffsetPointer(0));
uint8_t* dstBuffer = static_cast<uint8_t*>(nativeBuffer);
for(uint32_t i = 0; i < extent.height; i++)
{
memcpy(dstBuffer + (i * bufferRowBytes), srcBuffer + (i * imageRowBytes), imageRowBytes);
}
if(GrallocModule::getInstance()->unlock(backingMemory.nativeHandle) != 0)
{
return VK_ERROR_OUT_OF_DATE_KHR;
}
return VK_SUCCESS;
}
VkDeviceMemory Image::getExternalMemory() const
{
return backingMemory.externalMemory ? *deviceMemory : VkDeviceMemory{ VK_NULL_HANDLE };
}
#endif
void Image::getSubresourceLayout(const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const void Image::getSubresourceLayout(const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const
{ {
// By spec, aspectMask has a single bit set. // By spec, aspectMask has a single bit set.
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
#include "VkObject.hpp" #include "VkObject.hpp"
#include "VkFormat.h" #include "VkFormat.h"
#ifdef __ANDROID__
#include <vulkan/vk_android_native_buffer.h> // For VkSwapchainImageUsageFlagsANDROID and buffer_handle_t
#endif
namespace vk namespace vk
{ {
...@@ -25,12 +29,25 @@ class Buffer; ...@@ -25,12 +29,25 @@ class Buffer;
class Device; class Device;
class DeviceMemory; class DeviceMemory;
#ifdef __ANDROID__
struct BackingMemory {
int stride = 0;
bool externalMemory = false;
buffer_handle_t nativeHandle = nullptr;
VkSwapchainImageUsageFlagsANDROID androidUsage = 0;
};
#endif
class Image : public Object<Image, VkImage> class Image : public Object<Image, VkImage>
{ {
public: public:
Image(const VkImageCreateInfo* pCreateInfo, void* mem, Device *device); Image(const VkImageCreateInfo* pCreateInfo, void* mem, Device *device);
void destroy(const VkAllocationCallbacks* pAllocator); void destroy(const VkAllocationCallbacks* pAllocator);
#ifdef __ANDROID__
VkResult prepareForExternalUseANDROID() const;
#endif
static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo); static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo);
const VkMemoryRequirements getMemoryRequirements() const; const VkMemoryRequirements getMemoryRequirements() const;
...@@ -68,6 +85,12 @@ public: ...@@ -68,6 +85,12 @@ public:
void prepareForSampling(const VkImageSubresourceRange& subresourceRange); void prepareForSampling(const VkImageSubresourceRange& subresourceRange);
const Image* getSampledImage(const vk::Format& imageViewFormat) const; const Image* getSampledImage(const vk::Format& imageViewFormat) const;
#ifdef __ANDROID__
void setBackingMemory(BackingMemory& bm) { backingMemory = bm; }
bool hasExternalMemory() const { return backingMemory.externalMemory; }
VkDeviceMemory getExternalMemory() const;
#endif
private: private:
void copy(Buffer* buffer, const VkBufferImageCopy& region, bool bufferIsSource); void copy(Buffer* buffer, const VkBufferImageCopy& region, bool bufferIsSource);
VkDeviceSize getStorageSize(VkImageAspectFlags flags) const; VkDeviceSize getStorageSize(VkImageAspectFlags flags) const;
...@@ -99,6 +122,9 @@ private: ...@@ -99,6 +122,9 @@ private:
VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
VkImageUsageFlags usage = (VkImageUsageFlags)0; VkImageUsageFlags usage = (VkImageUsageFlags)0;
Image* decompressedImage = nullptr; Image* decompressedImage = nullptr;
#ifdef __ANDROID__
BackingMemory backingMemory = {};
#endif
}; };
static inline Image* Cast(VkImage object) static inline Image* Cast(VkImage object)
......
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
#endif #endif
#ifdef __ANDROID__ #ifdef __ANDROID__
#include <vulkan/vk_android_native_buffer.h>
#include "System/GrallocAndroid.hpp" #include "System/GrallocAndroid.hpp"
#include <sync/sync.h> #include <sync/sync.h>
#endif #endif
...@@ -1181,17 +1180,6 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(VkDevice device, VkBufferView buf ...@@ -1181,17 +1180,6 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(VkDevice device, VkBufferView buf
vk::destroy(bufferView, pAllocator); vk::destroy(bufferView, pAllocator);
} }
#ifdef __ANDROID__
struct BackingMemory {
buffer_handle_t nativeHandle;
int stride;
vk::DeviceMemory* 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) 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)", TRACE("(VkDevice device = %p, const VkImageCreateInfo* pCreateInfo = %p, const VkAllocationCallbacks* pAllocator = %p, VkImage* pImage = %p)",
...@@ -1200,7 +1188,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat ...@@ -1200,7 +1188,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat
const VkBaseInStructure* extensionCreateInfo = reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext); const VkBaseInStructure* extensionCreateInfo = reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext);
#ifdef __ANDROID__ #ifdef __ANDROID__
BackingMemory backmem; vk::BackingMemory backmem;
bool swapchainImage = false; bool swapchainImage = false;
#endif #endif
...@@ -1246,7 +1234,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat ...@@ -1246,7 +1234,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat
return result; return result;
} }
VkMemoryRequirements memRequirements = vk::Cast(*pImage)->getMemoryRequirements(); vk::Image* image = vk::Cast(*pImage);
VkMemoryRequirements memRequirements = image->getMemoryRequirements();
VkMemoryAllocateInfo allocInfo = {}; VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
...@@ -1254,16 +1243,16 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat ...@@ -1254,16 +1243,16 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat
allocInfo.memoryTypeIndex = 0; allocInfo.memoryTypeIndex = 0;
VkDeviceMemory devmem = { VK_NULL_HANDLE }; VkDeviceMemory devmem = { VK_NULL_HANDLE };
result = vkAllocateMemory(device, &allocInfo, nullptr, &devmem); result = vkAllocateMemory(device, &allocInfo, pAllocator, &devmem);
if(result != VK_SUCCESS) if(result != VK_SUCCESS)
{ {
return result; return result;
} }
backmem.imageMemory = vk::Cast(devmem);
vkBindImageMemory(device, *pImage, devmem, 0); vkBindImageMemory(device, *pImage, devmem, 0);
backmem.externalMemory = true;
androidSwapchainMap[*pImage] = backmem; image->setBackingMemory(backmem);
} }
#endif #endif
...@@ -1278,12 +1267,10 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const ...@@ -1278,12 +1267,10 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const
vk::destroy(image, pAllocator); vk::destroy(image, pAllocator);
#ifdef __ANDROID__ #ifdef __ANDROID__
auto it = androidSwapchainMap.find(image); vk::Image* img = vk::Cast(image);
if(img && img->hasExternalMemory())
if (it != androidSwapchainMap.end())
{ {
vk::destroy(static_cast<VkDeviceMemory>(*((it->second).imageMemory)), nullptr); vk::destroy(img->getExternalMemory(), pAllocator);
androidSwapchainMap.erase(it);
} }
#endif #endif
} }
...@@ -3153,29 +3140,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageANDROID(VkQueue queue, u ...@@ -3153,29 +3140,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageANDROID(VkQueue queue, u
// to get rid of it. b/132458423 // to get rid of it. b/132458423
vkQueueWaitIdle(queue); vkQueueWaitIdle(queue);
GrallocModule* grallocMod = GrallocModule::getInstance(); *pNativeFenceFd = -1;
void* nativeBuffer;
auto it = androidSwapchainMap.find(image);
if (it == androidSwapchainMap.end())
ABORT("ANDROID: Swapchain image not found");
BackingMemory backmem = it->second; return vk::Cast(image)->prepareForExternalUseANDROID();
VkExtent3D extent = vk::Cast(image)->getMipLevelExtent(VK_IMAGE_ASPECT_COLOR_BIT, 0);
grallocMod->lock(backmem.nativeHandle, GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, extent.width, extent.height, &nativeBuffer);
char* buffer = static_cast<char*>(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__ #endif // __ANDROID__
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment