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 @@
#include "Device/ETC_Decoder.hpp"
#include <cstring>
#ifdef __ANDROID__
#include "System/GrallocAndroid.hpp"
#endif
namespace
{
ETC_Decoder::InputType GetInputType(const vk::Format& format)
......@@ -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
{
// By spec, aspectMask has a single bit set.
......
......@@ -18,6 +18,10 @@
#include "VkObject.hpp"
#include "VkFormat.h"
#ifdef __ANDROID__
#include <vulkan/vk_android_native_buffer.h> // For VkSwapchainImageUsageFlagsANDROID and buffer_handle_t
#endif
namespace vk
{
......@@ -25,12 +29,25 @@ class Buffer;
class Device;
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>
{
public:
Image(const VkImageCreateInfo* pCreateInfo, void* mem, Device *device);
void destroy(const VkAllocationCallbacks* pAllocator);
#ifdef __ANDROID__
VkResult prepareForExternalUseANDROID() const;
#endif
static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo);
const VkMemoryRequirements getMemoryRequirements() const;
......@@ -68,6 +85,12 @@ public:
void prepareForSampling(const VkImageSubresourceRange& subresourceRange);
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:
void copy(Buffer* buffer, const VkBufferImageCopy& region, bool bufferIsSource);
VkDeviceSize getStorageSize(VkImageAspectFlags flags) const;
......@@ -99,6 +122,9 @@ private:
VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
VkImageUsageFlags usage = (VkImageUsageFlags)0;
Image* decompressedImage = nullptr;
#ifdef __ANDROID__
BackingMemory backingMemory = {};
#endif
};
static inline Image* Cast(VkImage object)
......
......@@ -59,7 +59,6 @@
#endif
#ifdef __ANDROID__
#include <vulkan/vk_android_native_buffer.h>
#include "System/GrallocAndroid.hpp"
#include <sync/sync.h>
#endif
......@@ -1181,17 +1180,6 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(VkDevice device, VkBufferView buf
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)
{
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
const VkBaseInStructure* extensionCreateInfo = reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext);
#ifdef __ANDROID__
BackingMemory backmem;
vk::BackingMemory backmem;
bool swapchainImage = false;
#endif
......@@ -1246,7 +1234,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat
return result;
}
VkMemoryRequirements memRequirements = vk::Cast(*pImage)->getMemoryRequirements();
vk::Image* image = vk::Cast(*pImage);
VkMemoryRequirements memRequirements = image->getMemoryRequirements();
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
......@@ -1254,16 +1243,16 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat
allocInfo.memoryTypeIndex = 0;
VkDeviceMemory devmem = { VK_NULL_HANDLE };
result = vkAllocateMemory(device, &allocInfo, nullptr, &devmem);
result = vkAllocateMemory(device, &allocInfo, pAllocator, &devmem);
if(result != VK_SUCCESS)
{
return result;
}
backmem.imageMemory = vk::Cast(devmem);
vkBindImageMemory(device, *pImage, devmem, 0);
backmem.externalMemory = true;
androidSwapchainMap[*pImage] = backmem;
image->setBackingMemory(backmem);
}
#endif
......@@ -1278,12 +1267,10 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const
vk::destroy(image, pAllocator);
#ifdef __ANDROID__
auto it = androidSwapchainMap.find(image);
if (it != androidSwapchainMap.end())
vk::Image* img = vk::Cast(image);
if(img && img->hasExternalMemory())
{
vk::destroy(static_cast<VkDeviceMemory>(*((it->second).imageMemory)), nullptr);
androidSwapchainMap.erase(it);
vk::destroy(img->getExternalMemory(), pAllocator);
}
#endif
}
......@@ -3153,29 +3140,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageANDROID(VkQueue queue, u
// to get rid of it. b/132458423
vkQueueWaitIdle(queue);
GrallocModule* grallocMod = GrallocModule::getInstance();
void* nativeBuffer;
auto it = androidSwapchainMap.find(image);
if (it == androidSwapchainMap.end())
ABORT("ANDROID: Swapchain image not found");
*pNativeFenceFd = -1;
BackingMemory backmem = it->second;
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;
return vk::Cast(image)->prepareForExternalUseANDROID();
}
#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