Commit 4bc9f6e5 by Jason Macnak

Update SwiftShader VK AHB to support generic gralloc

... by only using the AHardwareBuffer_* functions which will use the device's gralloc implementation. Note: this change does not fix the 5 existing deqp failures in the suballocated.* tests that are mentioned in b/169796031. Note: ANGLE doesn't seem to have support for VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM yet: b/171302758. Bug: b/141698760 Bug: b/147316305 Test: launch_cvd && cts -m CtsDeqpTestCases dEQP-VK.api.external.memory.android_hardware_buffer.* Change-Id: Ia551e78198c20d6c40ffa9448418f73829da1880 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/49248 Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarJason Macnak <natsu@google.com> Reviewed-by: 's avatarTrevor Black <vantablack@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent ec526abc
...@@ -56,7 +56,6 @@ cc_defaults { ...@@ -56,7 +56,6 @@ cc_defaults {
shared_libs: [ shared_libs: [
"android.hardware.graphics.mapper@3.0", "android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0", "android.hardware.graphics.mapper@4.0",
"libdrm",
"libnativewindow", "libnativewindow",
"libhardware", "libhardware",
"libhidlbase", "libhidlbase",
...@@ -591,7 +590,6 @@ cc_defaults { ...@@ -591,7 +590,6 @@ cc_defaults {
shared_libs: [ shared_libs: [
"android.hardware.graphics.mapper@3.0", "android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0", "android.hardware.graphics.mapper@4.0",
"libdrm",
"libnativewindow", "libnativewindow",
"libhardware", "libhardware",
"libhidlbase", "libhidlbase",
...@@ -664,8 +662,6 @@ cc_defaults { ...@@ -664,8 +662,6 @@ cc_defaults {
include_dirs: [ include_dirs: [
"external/swiftshader/third_party/SPIRV-Headers/include", "external/swiftshader/third_party/SPIRV-Headers/include",
"external/swiftshader/include", "external/swiftshader/include",
"external/minigbm",
"external/libdrm"
], ],
} }
......
...@@ -41,6 +41,9 @@ public: ...@@ -41,6 +41,9 @@ public:
uint8_t *end() const; uint8_t *end() const;
bool canBindToMemory(DeviceMemory *pDeviceMemory) const; bool canBindToMemory(DeviceMemory *pDeviceMemory) const;
VkBufferUsageFlags getUsage() const { return usage; }
VkBufferCreateFlags getFlags() const { return flags; }
private: private:
void *memory = nullptr; void *memory = nullptr;
VkBufferCreateFlags flags = 0; VkBufferCreateFlags flags = 0;
......
...@@ -146,10 +146,6 @@ Device::Device(const VkDeviceCreateInfo *pCreateInfo, void *mem, PhysicalDevice ...@@ -146,10 +146,6 @@ Device::Device(const VkDeviceCreateInfo *pCreateInfo, void *mem, PhysicalDevice
debugger.server = vk::dbg::Server::create(debugger.context, atoi(port)); debugger.server = vk::dbg::Server::create(debugger.context, atoi(port));
} }
#endif // ENABLE_VK_DEBUGGER #endif // ENABLE_VK_DEBUGGER
#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
ahbAddressMap.reset(new AHBAddressMap());
#endif
} }
void Device::destroy(const VkAllocationCallbacks *pAllocator) void Device::destroy(const VkAllocationCallbacks *pAllocator)
...@@ -379,60 +375,4 @@ void Device::contentsChanged(ImageView *imageView) ...@@ -379,60 +375,4 @@ void Device::contentsChanged(ImageView *imageView)
} }
} }
#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
Device::AHBAddressMap *Device::getAHBAddressMap() const
{
return ahbAddressMap.get();
}
void *Device::AHBAddressMap::query(const uint32_t key)
{
std::unique_lock<std::mutex> lock(addressMapMutex);
if(addressMap.find(key) == addressMap.end())
return nullptr;
return addressMap[key].address;
}
void Device::AHBAddressMap::add(const uint32_t key, void *value)
{
std::unique_lock<std::mutex> lock(addressMapMutex);
auto it = addressMap.find(key);
if(it == addressMap.end())
{
MapValue mv;
mv.refCount = 1;
mv.address = value;
addressMap[key] = mv;
}
else
{
it->second.address = value;
it->second.refCount++;
}
}
int Device::AHBAddressMap::incrementReference(const uint32_t key)
{
std::unique_lock<std::mutex> lock(addressMapMutex);
auto it = addressMap.find(key);
if(it == addressMap.end())
return -1;
it->second.refCount++;
return it->second.refCount;
}
int Device::AHBAddressMap::decrementReference(const uint32_t key)
{
std::unique_lock<std::mutex> lock(addressMapMutex);
auto it = addressMap.find(key);
if(it == addressMap.end())
return -1;
it->second.refCount--;
return it->second.refCount;
}
#endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
} // namespace vk } // namespace vk
...@@ -193,41 +193,6 @@ private: ...@@ -193,41 +193,6 @@ private:
std::shared_ptr<vk::dbg::Server> server; std::shared_ptr<vk::dbg::Server> server;
} debugger; } debugger;
#endif // ENABLE_VK_DEBUGGER #endif // ENABLE_VK_DEBUGGER
#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
public:
class AHBAddressMap
{
public:
AHBAddressMap() {}
~AHBAddressMap() {}
struct MapValue
{
MapValue()
: refCount(0)
, address(nullptr)
{
}
int refCount;
void *address;
};
void *query(const uint32_t key);
int incrementReference(const uint32_t key);
int decrementReference(const uint32_t key);
void add(const uint32_t key, void *value);
private:
std::map<uint32_t, MapValue> addressMap;
std::mutex addressMapMutex;
};
AHBAddressMap *getAHBAddressMap() const;
private:
std::unique_ptr<AHBAddressMap> ahbAddressMap;
#endif
}; };
using DispatchableDevice = DispatchableObject<Device, VkDevice>; using DispatchableDevice = DispatchableObject<Device, VkDevice>;
......
...@@ -16,159 +16,19 @@ ...@@ -16,159 +16,19 @@
# include "VkDeviceMemoryExternalAndroid.hpp" # include "VkDeviceMemoryExternalAndroid.hpp"
# include "System/Debug.hpp"
# include "VkDestroy.hpp" # include "VkDestroy.hpp"
# include "VkDevice.hpp"
# include "VkFormat.hpp" # include "VkFormat.hpp"
# include "VkObject.hpp" # include "VkObject.hpp"
# include "VkPhysicalDevice.hpp" # include "VkPhysicalDevice.hpp"
# include "VkStringify.hpp"
# include "System/Debug.hpp"
# include "System/Linux/MemFd.hpp"
# include <sys/mman.h>
# include <android/hardware_buffer.h> # include <android/hardware_buffer.h>
# include <cutils/native_handle.h>
# include <vndk/hardware_buffer.h> # include <vndk/hardware_buffer.h>
# include <cros_gralloc/cros_gralloc_handle.h> namespace {
# include <external/virgl_hw.h>
# include <unistd.h>
# include <virtgpu_drm.h>
# include <xf86drm.h>
AHardwareBufferExternalMemory::~AHardwareBufferExternalMemory()
{
// correct deallocation of AHB does not require a pointer or size
deallocate(nullptr, 0);
}
VkResult AHardwareBufferExternalMemory::allocate(size_t size, void **pBuffer)
{
if(allocateInfo.importAhb)
{
ahb = allocateInfo.ahb;
AHardwareBuffer_acquire(ahb);
return allocateAndroidHardwareBuffer(size, pBuffer);
}
else
{
ASSERT(allocateInfo.exportAhb);
// Outline ahbDesc
AHardwareBuffer_Desc ahbDesc;
if(allocateInfo.imageHandle)
{
ahbDesc.format = GetAndroidHardwareBufferDescFormat(VkFormat(allocateInfo.imageHandle->getFormat()));
VkExtent3D extent = allocateInfo.imageHandle->getMipLevelExtent(VK_IMAGE_ASPECT_COLOR_BIT, 0);
ahbDesc.width = extent.width;
ahbDesc.height = extent.height;
ahbDesc.layers = allocateInfo.imageHandle->getArrayLayers();
ahbDesc.stride = allocateInfo.imageHandle->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
VkImageCreateFlags createFlags = allocateInfo.imageHandle->getFlags();
VkImageUsageFlags usageFlags = allocateInfo.imageHandle->getUsage();
GetAndroidHardwareBufferUsageFromVkUsage(createFlags, usageFlags, ahbDesc.usage);
}
else
{
ASSERT(allocateInfo.bufferHandle);
ahbDesc.format = AHARDWAREBUFFER_FORMAT_BLOB;
ahbDesc.width = uint32_t(allocateInfo.bufferHandle->getSize());
ahbDesc.height = 1;
ahbDesc.layers = 1;
ahbDesc.stride = uint32_t(allocateInfo.bufferHandle->getSize());
// TODO(b/141698760)
// This will be fairly specific, needs fleshing out
ahbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
}
// create a new ahb from desc
if(AHardwareBuffer_allocate(&ahbDesc, &ahb) != 0)
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
return allocateAndroidHardwareBuffer(size, pBuffer);
}
}
VkResult AHardwareBufferExternalMemory::allocateAndroidHardwareBuffer(size_t size, void **pBuffer)
{
// get native_handle_t from ahb
const native_handle_t *h = AHardwareBuffer_getNativeHandle(ahb);
if(h == nullptr)
{
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
// get rendernodeFD and primeHandle from native_handle_t.data
uint32_t primeHandle;
createRenderNodeFD();
VkResult result = getPrimeHandle(h, primeHandle);
if(result != VK_SUCCESS)
{
return result;
}
// get memory pointer from store or mmap it
vk::Device::AHBAddressMap *pDeviceHandleMap = device->getAHBAddressMap();
void *pAddress = pDeviceHandleMap->query(primeHandle);
if(pAddress != nullptr)
{
*pBuffer = pAddress;
pDeviceHandleMap->incrementReference(primeHandle);
}
else
{
// map memory
void *ptr;
VkResult result = mapMemory(primeHandle, &ptr);
if(result != VK_SUCCESS)
{
return result;
}
// Add primeHandle and ptr to deviceHandleMap
pDeviceHandleMap->add(primeHandle, ptr);
*pBuffer = pDeviceHandleMap->query(primeHandle);
}
return VK_SUCCESS;
}
void AHardwareBufferExternalMemory::deallocate(void *buffer, size_t size)
{
if(ahb != nullptr)
{
const native_handle_t *h = AHardwareBuffer_getNativeHandle(ahb);
uint32_t primeHandle;
VkResult result = getPrimeHandle(h, primeHandle);
ASSERT(result == VK_SUCCESS);
// close gpu memory and rendernodeFD
vk::Device::AHBAddressMap *pDeviceHandleMap = device->getAHBAddressMap();
if(pDeviceHandleMap->decrementReference(primeHandle) == 0)
{
closeMemory(primeHandle);
}
close(rendernodeFD);
AHardwareBuffer_release(ahb); uint32_t GetAHBFormatFromVkFormat(VkFormat format)
ahb = nullptr;
}
}
VkResult AHardwareBufferExternalMemory::exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const
{
// Each call to vkGetMemoryAndroidHardwareBufferANDROID *must* return an Android hardware buffer with a new reference
// acquired in addition to the reference held by the VkDeviceMemory. To avoid leaking resources, the application *must*
// release the reference by calling AHardwareBuffer_release when it is no longer needed.
AHardwareBuffer_acquire(ahb);
*pAhb = ahb;
return VK_SUCCESS;
}
uint32_t AHardwareBufferExternalMemory::GetAndroidHardwareBufferDescFormat(VkFormat format)
{ {
switch(format) switch(format)
{ {
...@@ -204,7 +64,7 @@ uint32_t AHardwareBufferExternalMemory::GetAndroidHardwareBufferDescFormat(VkFor ...@@ -204,7 +64,7 @@ uint32_t AHardwareBufferExternalMemory::GetAndroidHardwareBufferDescFormat(VkFor
} }
} }
VkFormat AHardwareBufferExternalMemory::GetVkFormat(uint32_t ahbFormat) VkFormat GetVkFormatFromAHBFormat(uint32_t ahbFormat)
{ {
switch(ahbFormat) switch(ahbFormat)
{ {
...@@ -244,159 +104,111 @@ VkFormat AHardwareBufferExternalMemory::GetVkFormat(uint32_t ahbFormat) ...@@ -244,159 +104,111 @@ VkFormat AHardwareBufferExternalMemory::GetVkFormat(uint32_t ahbFormat)
} }
} }
VkFormatFeatureFlags AHardwareBufferExternalMemory::GetVkFormatFeatures(VkFormat format) uint64_t GetAHBLockUsageFromVkImageUsageFlags(VkImageUsageFlags flags)
{
VkFormatProperties formatProperties;
vk::PhysicalDevice::GetFormatProperties(vk::Format(format), &formatProperties);
formatProperties.optimalTilingFeatures |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
// TODO: b/167896057
// The correct formatFeatureFlags depends on consumer and format
// So this solution is incomplete without more information
return formatProperties.linearTilingFeatures | formatProperties.optimalTilingFeatures | formatProperties.bufferFeatures;
}
VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferFormatProperties(const AHardwareBuffer_Desc &ahbDesc, VkAndroidHardwareBufferFormatPropertiesANDROID *pFormat)
{ {
uint64_t usage = 0;
pFormat->sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; if(flags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT ||
pFormat->pNext = nullptr; flags & VK_IMAGE_USAGE_SAMPLED_BIT ||
flags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
pFormat->format = GetVkFormat(ahbDesc.format); {
pFormat->externalFormat = ahbDesc.format; usage |= AHARDWAREBUFFER_USAGE_CPU_READ_MASK;
pFormat->formatFeatures = GetVkFormatFeatures(pFormat->format); }
pFormat->samplerYcbcrConversionComponents = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; if(flags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ||
pFormat->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; flags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
pFormat->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; {
pFormat->suggestedXChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK;
pFormat->suggestedYChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; }
return VK_SUCCESS; return usage;
} }
VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferProperties(VkDevice &device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties) uint64_t GetAHBLockUsageFromVkBufferUsageFlags(VkBufferUsageFlags flags)
{ {
AHardwareBuffer_Desc ahbDesc; uint64_t usage = 0;
AHardwareBuffer_describe(buffer, &ahbDesc);
GetAndroidHardwareBufferFormatProperties(ahbDesc, (VkAndroidHardwareBufferFormatPropertiesANDROID *)pProperties->pNext);
const VkPhysicalDeviceMemoryProperties phyDeviceMemProps = vk::PhysicalDevice::GetMemoryProperties(); if(flags & VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
pProperties->memoryTypeBits = phyDeviceMemProps.memoryTypes[0].propertyFlags;
if(ahbDesc.format == AHARDWAREBUFFER_FORMAT_BLOB)
{ {
pProperties->allocationSize = ahbDesc.width; usage |= AHARDWAREBUFFER_USAGE_CPU_READ_MASK;
} }
else
{
VkImageCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.imageType = VK_IMAGE_TYPE_2D;
info.format = GetVkFormat(ahbDesc.format);
info.extent.width = ahbDesc.width;
info.extent.height = ahbDesc.height;
info.extent.depth = 1;
info.mipLevels = 1;
info.arrayLayers = 1;
info.samples = VK_SAMPLE_COUNT_1_BIT;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkImage Image; if(flags & VK_BUFFER_USAGE_TRANSFER_DST_BIT)
VkResult result = vk::Image::Create(vk::DEVICE_MEMORY, &info, &Image, vk::Cast(device)); {
usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK;
pProperties->allocationSize = vk::Cast(Image)->getMemoryRequirements().size;
vk::destroy(Image, vk::DEVICE_MEMORY);
} }
return VK_SUCCESS; return usage;
} }
VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags createFlags, const VkImageUsageFlags usageFlags, uint64_t &ahbDescUsage) uint64_t GetAHBUsageFromVkImageFlags(VkImageCreateFlags createFlags, VkImageUsageFlags usageFlags)
{ {
uint64_t ahbUsage = 0;
if(usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) if(usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)
ahbDescUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; {
ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
}
if(usageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) if(usageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
ahbDescUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; {
ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
}
if(usageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) if(usageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
ahbDescUsage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; {
ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
}
if(createFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) if(createFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
ahbDescUsage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; {
ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
}
if(createFlags & VK_IMAGE_CREATE_PROTECTED_BIT) if(createFlags & VK_IMAGE_CREATE_PROTECTED_BIT)
ahbDescUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; {
ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
}
// No usage bits set - set at least one GPU usage // No usage bits set - set at least one GPU usage
if(ahbDescUsage == 0) if(ahbUsage == 0)
ahbDescUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
return VK_SUCCESS;
}
// Call into the native gralloc implementation to request a handle for the
// rendernodeFD
VkResult AHardwareBufferExternalMemory::getPrimeHandle(const native_handle_t *h, uint32_t &primeHandle)
{
cros_gralloc_handle const *crosHandle = reinterpret_cast<cros_gralloc_handle const *>(h);
int ret = drmPrimeFDToHandle(rendernodeFD, crosHandle->fds[0], &primeHandle);
if(ret != 0)
{ {
return VK_ERROR_INVALID_EXTERNAL_HANDLE; ahbUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
} }
return VK_SUCCESS; return ahbUsage;
} }
// Create a rendernodeFD uint64_t GetAHBUsageFromVkBufferFlags(VkBufferCreateFlags /*createFlags*/, VkBufferUsageFlags /*usageFlags*/)
void AHardwareBufferExternalMemory::createRenderNodeFD()
{ {
rendernodeFD = drmOpenRender(128); uint64_t ahbUsage = 0;
// TODO(b/141698760): needs fleshing out.
ahbUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
return ahbUsage;
} }
// using a primeHandle associated with a specific rendernodeFD, map a new block VkFormatFeatureFlags GetVkFormatFeaturesFromAHBFormat(uint32_t ahbFormat)
// of memory
VkResult AHardwareBufferExternalMemory::mapMemory(uint32_t &primeHandle, void **ptr)
{ {
drm_virtgpu_map map; VkFormatFeatureFlags features = 0;
memset(&map, 0, sizeof(drm_virtgpu_map));
map.handle = primeHandle;
int ret = drmIoctl(rendernodeFD, DRM_IOCTL_VIRTGPU_MAP, &map);
if(ret != 0)
{
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
// mmap it VkFormat format = GetVkFormatFromAHBFormat(ahbFormat);
*ptr = static_cast<unsigned char *>( VkFormatProperties formatProperties;
mmap64(nullptr, 4096, PROT_WRITE, MAP_SHARED, rendernodeFD, map.offset)); vk::PhysicalDevice::GetFormatProperties(vk::Format(format), &formatProperties);
if(ptr == MAP_FAILED)
{
return VK_ERROR_MEMORY_MAP_FAILED;
}
return VK_SUCCESS; formatProperties.optimalTilingFeatures |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
}
// Close out the memory block associated with rendernodeFD // TODO: b/167896057
VkResult AHardwareBufferExternalMemory::closeMemory(uint32_t &primeHandle) // The correct formatFeatureFlags depends on consumer and format
{ // So this solution is incomplete without more information
struct drm_gem_close gem_close; features |= formatProperties.linearTilingFeatures |
memset(&gem_close, 0x0, sizeof(gem_close)); formatProperties.optimalTilingFeatures |
gem_close.handle = primeHandle; formatProperties.bufferFeatures;
int ret = drmIoctl(rendernodeFD, DRM_IOCTL_GEM_CLOSE, &gem_close);
if(ret != 0)
{
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
return VK_SUCCESS; return features;
} }
} // namespace
AHardwareBufferExternalMemory::AllocateInfo::AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) AHardwareBufferExternalMemory::AllocateInfo::AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
{ {
const auto *createInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext); const auto *createInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
...@@ -415,11 +227,14 @@ AHardwareBufferExternalMemory::AllocateInfo::AllocateInfo(const VkMemoryAllocate ...@@ -415,11 +227,14 @@ AHardwareBufferExternalMemory::AllocateInfo::AllocateInfo(const VkMemoryAllocate
{ {
const auto *exportInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(createInfo); const auto *exportInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(createInfo);
if(exportInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) if(exportInfo->handleTypes == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
{
exportAhb = true;
}
else
{ {
UNSUPPORTED("VkExportMemoryAllocateInfo::handleTypes %d", int(exportInfo->handleTypes)); UNSUPPORTED("VkExportMemoryAllocateInfo::handleTypes %d", int(exportInfo->handleTypes));
} }
exportAhb = true;
} }
break; break;
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
...@@ -439,4 +254,208 @@ AHardwareBufferExternalMemory::AllocateInfo::AllocateInfo(const VkMemoryAllocate ...@@ -439,4 +254,208 @@ AHardwareBufferExternalMemory::AllocateInfo::AllocateInfo(const VkMemoryAllocate
} }
} }
AHardwareBufferExternalMemory::AHardwareBufferExternalMemory(const VkMemoryAllocateInfo *pAllocateInfo)
: allocateInfo(pAllocateInfo)
{
}
AHardwareBufferExternalMemory::~AHardwareBufferExternalMemory()
{
// correct deallocation of AHB does not require a pointer or size
deallocate(nullptr, 0);
}
// VkAllocateMemory
VkResult AHardwareBufferExternalMemory::allocate(size_t /*size*/, void **pBuffer)
{
if(allocateInfo.importAhb)
{
return importAndroidHardwareBuffer(allocateInfo.ahb, pBuffer);
}
else
{
ASSERT(allocateInfo.exportAhb);
return allocateAndroidHardwareBuffer(pBuffer);
}
}
void AHardwareBufferExternalMemory::deallocate(void *buffer, size_t size)
{
if(ahb != nullptr)
{
unlockAndroidHardwareBuffer();
AHardwareBuffer_release(ahb);
ahb = nullptr;
}
}
VkResult AHardwareBufferExternalMemory::importAndroidHardwareBuffer(struct AHardwareBuffer *buffer, void **pBuffer)
{
ahb = buffer;
AHardwareBuffer_acquire(ahb);
return lockAndroidHardwareBuffer(pBuffer);
}
VkResult AHardwareBufferExternalMemory::allocateAndroidHardwareBuffer(void **pBuffer)
{
AHardwareBuffer_Desc desc = {};
if(allocateInfo.imageHandle)
{
vk::Image *image = allocateInfo.imageHandle;
ASSERT(image != nullptr);
ASSERT(image->getArrayLayers() == 1);
VkExtent3D extent = image->getExtent();
desc.width = extent.width;
desc.height = extent.height;
desc.layers = image->getArrayLayers();
desc.format = GetAHBFormatFromVkFormat(image->getFormat());
desc.usage = GetAHBUsageFromVkImageFlags(image->getFlags(), image->getUsage());
}
else
{
vk::Buffer *buffer = allocateInfo.bufferHandle;
ASSERT(buffer != nullptr);
desc.width = static_cast<uint32_t>(buffer->getSize());
desc.height = 1;
desc.layers = 1;
desc.format = AHARDWAREBUFFER_FORMAT_BLOB;
desc.usage = GetAHBUsageFromVkBufferFlags(buffer->getFlags(), buffer->getUsage());
}
// create a new ahb from desc
int ret = AHardwareBuffer_allocate(&desc, &ahb);
if(ret != 0)
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
return lockAndroidHardwareBuffer(pBuffer);
}
VkResult AHardwareBufferExternalMemory::lockAndroidHardwareBuffer(void **pBuffer)
{
uint64_t usage = 0;
if(allocateInfo.imageHandle)
{
usage = GetAHBLockUsageFromVkImageUsageFlags(allocateInfo.imageHandle->getUsage());
}
else
{
usage = GetAHBLockUsageFromVkBufferUsageFlags(allocateInfo.bufferHandle->getUsage());
}
// Empty fence, lock immedietly.
int32_t fence = -1;
// Empty rect, lock entire buffer.
ARect *rect = nullptr;
int ret = AHardwareBuffer_lock(ahb, usage, fence, rect, pBuffer);
if(ret != 0)
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
return VK_SUCCESS;
}
VkResult AHardwareBufferExternalMemory::unlockAndroidHardwareBuffer()
{
int ret = AHardwareBuffer_unlock(ahb, /*fence=*/nullptr);
if(ret != 0)
{
return VK_ERROR_UNKNOWN;
}
return VK_SUCCESS;
}
VkResult AHardwareBufferExternalMemory::exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const
{
// Each call to vkGetMemoryAndroidHardwareBufferANDROID *must* return an Android hardware buffer with a new reference
// acquired in addition to the reference held by the VkDeviceMemory. To avoid leaking resources, the application *must*
// release the reference by calling AHardwareBuffer_release when it is no longer needed.
AHardwareBuffer_acquire(ahb);
*pAhb = ahb;
return VK_SUCCESS;
}
VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferFormatProperties(const AHardwareBuffer_Desc &ahbDesc, VkAndroidHardwareBufferFormatPropertiesANDROID *pFormat)
{
pFormat->sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
pFormat->pNext = nullptr;
pFormat->format = GetVkFormatFromAHBFormat(ahbDesc.format);
pFormat->externalFormat = ahbDesc.format;
pFormat->formatFeatures = GetVkFormatFeaturesFromAHBFormat(ahbDesc.format);
pFormat->samplerYcbcrConversionComponents = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
pFormat->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
pFormat->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
pFormat->suggestedXChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
pFormat->suggestedYChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
return VK_SUCCESS;
}
VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferProperties(VkDevice &device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
{
VkResult result = VK_SUCCESS;
AHardwareBuffer_Desc ahbDesc;
AHardwareBuffer_describe(buffer, &ahbDesc);
if(pProperties->pNext != nullptr)
{
result = GetAndroidHardwareBufferFormatProperties(ahbDesc, (VkAndroidHardwareBufferFormatPropertiesANDROID *)pProperties->pNext);
if(result != VK_SUCCESS)
{
return result;
}
}
const VkPhysicalDeviceMemoryProperties phyDeviceMemProps = vk::PhysicalDevice::GetMemoryProperties();
pProperties->memoryTypeBits = phyDeviceMemProps.memoryTypes[0].propertyFlags;
if(ahbDesc.format == AHARDWAREBUFFER_FORMAT_BLOB)
{
pProperties->allocationSize = ahbDesc.width;
}
else
{
VkImageCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.imageType = VK_IMAGE_TYPE_2D;
info.format = GetVkFormatFromAHBFormat(ahbDesc.format);
info.extent.width = ahbDesc.width;
info.extent.height = ahbDesc.height;
info.extent.depth = 1;
info.mipLevels = 1;
info.arrayLayers = 1;
info.samples = VK_SAMPLE_COUNT_1_BIT;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkImage Image;
result = vk::Image::Create(vk::DEVICE_MEMORY, &info, &Image, vk::Cast(device));
if(result != VK_SUCCESS)
{
return result;
}
pProperties->allocationSize = vk::Cast(Image)->getMemoryRequirements().size;
vk::destroy(Image, vk::DEVICE_MEMORY);
}
return result;
}
#endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER #endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
...@@ -17,29 +17,14 @@ ...@@ -17,29 +17,14 @@
#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
# include "VkBuffer.hpp"
# include "VkDevice.hpp" # include "VkDevice.hpp"
# include "VkDeviceMemory.hpp" # include "VkDeviceMemory.hpp"
# include "VkDeviceMemoryExternalBase.hpp" # include "VkDeviceMemoryExternalBase.hpp"
# include "VkBuffer.hpp"
# include "VkDeviceMemory.hpp"
# include "VkImage.hpp" # include "VkImage.hpp"
# include "VkStringify.hpp"
# include "System/Debug.hpp"
# include "System/Linux/MemFd.hpp"
# include <android/hardware_buffer.h> # include <android/hardware_buffer.h>
# include <cros_gralloc/cros_gralloc_handle.h>
# include <unistd.h>
# include <virtgpu_drm.h>
# include <xf86drm.h>
# include <errno.h>
# include <string.h>
# include <map>
class AHardwareBufferExternalMemory : public vk::DeviceMemory::ExternalBase class AHardwareBufferExternalMemory : public vk::DeviceMemory::ExternalBase
{ {
public: public:
...@@ -68,49 +53,29 @@ public: ...@@ -68,49 +53,29 @@ public:
return (info.importAhb || info.exportAhb) && (info.bufferHandle || info.imageHandle); return (info.importAhb || info.exportAhb) && (info.bufferHandle || info.imageHandle);
} }
explicit AHardwareBufferExternalMemory(const VkMemoryAllocateInfo *pAllocateInfo) explicit AHardwareBufferExternalMemory(const VkMemoryAllocateInfo *pAllocateInfo);
: allocateInfo(pAllocateInfo)
{
}
~AHardwareBufferExternalMemory(); ~AHardwareBufferExternalMemory();
VkResult allocate(size_t size, void **pBuffer) override; VkResult allocate(size_t size, void **pBuffer) override;
void deallocate(void *buffer, size_t size) override; void deallocate(void *buffer, size_t size) override;
VkResult allocateAndroidHardwareBuffer(size_t size, void **pBuffer);
VkExternalMemoryHandleTypeFlagBits getFlagBit() const override VkExternalMemoryHandleTypeFlagBits getFlagBit() const override { return typeFlagBit; }
{
return typeFlagBit;
}
VkResult exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const override; VkResult exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const override;
void setDevicePtr(vk::Device *pDevice) override void setDevicePtr(vk::Device *pDevice) override { device = pDevice; }
{ bool isAndroidHardwareBuffer() override { return true; }
device = pDevice;
}
bool isAndroidHardwareBuffer() override
{
return true;
}
static uint32_t GetAndroidHardwareBufferDescFormat(VkFormat format);
static VkFormat GetVkFormat(uint32_t ahbFormat);
static VkFormatFeatureFlags GetVkFormatFeatures(VkFormat format);
static VkResult GetAndroidHardwareBufferFormatProperties(const AHardwareBuffer_Desc &ahbDesc, VkAndroidHardwareBufferFormatPropertiesANDROID *pFormat); static VkResult GetAndroidHardwareBufferFormatProperties(const AHardwareBuffer_Desc &ahbDesc, VkAndroidHardwareBufferFormatPropertiesANDROID *pFormat);
static VkResult GetAndroidHardwareBufferProperties(VkDevice &device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties); static VkResult GetAndroidHardwareBufferProperties(VkDevice &device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties);
static VkResult GetAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags createFlags, const VkImageUsageFlags usageFlags, uint64_t &ahbDescUsage);
// All reliance on minigbm and DRM is contained in these functions
VkResult getPrimeHandle(const native_handle_t *h, uint32_t &primeHandle);
void createRenderNodeFD();
VkResult mapMemory(uint32_t &primeHandle, void **ptr);
VkResult closeMemory(uint32_t &primeHandle);
private: private:
VkResult importAndroidHardwareBuffer(struct AHardwareBuffer *buffer, void **pBuffer);
VkResult allocateAndroidHardwareBuffer(void **pBuffer);
VkResult lockAndroidHardwareBuffer(void **pBuffer);
VkResult unlockAndroidHardwareBuffer();
struct AHardwareBuffer *ahb = nullptr; struct AHardwareBuffer *ahb = nullptr;
int rendernodeFD;
vk::Device *device = nullptr; vk::Device *device = nullptr;
AllocateInfo allocateInfo; AllocateInfo allocateInfo;
}; };
......
...@@ -529,108 +529,24 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties(VkPhysic ...@@ -529,108 +529,24 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties(VkPhysic
TRACE("(VkPhysicalDevice physicalDevice = %p, VkFormat format = %d, VkImageType type = %d, VkImageTiling tiling = %d, VkImageUsageFlags usage = %d, VkImageCreateFlags flags = %d, VkImageFormatProperties* pImageFormatProperties = %p)", TRACE("(VkPhysicalDevice physicalDevice = %p, VkFormat format = %d, VkImageType type = %d, VkImageTiling tiling = %d, VkImageUsageFlags usage = %d, VkImageCreateFlags flags = %d, VkImageFormatProperties* pImageFormatProperties = %p)",
physicalDevice, (int)format, (int)type, (int)tiling, usage, flags, pImageFormatProperties); physicalDevice, (int)format, (int)type, (int)tiling, usage, flags, pImageFormatProperties);
// "If the combination of parameters to vkGetPhysicalDeviceImageFormatProperties is not supported by the implementation VkPhysicalDeviceImageFormatInfo2 info2 = {};
// for use in vkCreateImage, then all members of VkImageFormatProperties will be filled with zero." info2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
memset(pImageFormatProperties, 0, sizeof(VkImageFormatProperties)); info2.pNext = nullptr;
info2.format = format;
VkFormatProperties properties; info2.type = type;
vk::PhysicalDevice::GetFormatProperties(format, &properties); info2.tiling = tiling;
info2.usage = usage;
VkFormatFeatureFlags features; info2.flags = flags;
switch(tiling)
{
case VK_IMAGE_TILING_LINEAR:
features = properties.linearTilingFeatures;
break;
case VK_IMAGE_TILING_OPTIMAL:
features = properties.optimalTilingFeatures;
break;
default:
UNSUPPORTED("VkImageTiling %d", int(tiling));
features = 0;
}
if(features == 0)
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
// Check for usage conflict with features VkImageFormatProperties2 properties2 = {};
if((usage & VK_IMAGE_USAGE_SAMPLED_BIT) && !(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) properties2.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
{ properties2.pNext = nullptr;
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_STORAGE_BIT) && !(features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !(features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) VkResult result = vkGetPhysicalDeviceImageFormatProperties2(physicalDevice, &info2, &properties2);
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) && !(features & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))) *pImageFormatProperties = properties2.imageFormatProperties;
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) && !(features & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) return result;
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) && !(features & VK_FORMAT_FEATURE_TRANSFER_DST_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
auto allRecognizedUsageBits = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
ASSERT(!(usage & ~(allRecognizedUsageBits)));
// "Images created with tiling equal to VK_IMAGE_TILING_LINEAR have further restrictions on their limits and capabilities
// compared to images created with tiling equal to VK_IMAGE_TILING_OPTIMAL."
if(tiling == VK_IMAGE_TILING_LINEAR)
{
if(type != VK_IMAGE_TYPE_2D)
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if(vk::Format(format).isDepth() || vk::Format(format).isStencil())
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
}
// "Images created with a format from one of those listed in Formats requiring sampler Y'CBCR conversion for VK_IMAGE_ASPECT_COLOR_BIT image views
// have further restrictions on their limits and capabilities compared to images created with other formats."
if(vk::Format(format).isYcbcrFormat())
{
if(type != VK_IMAGE_TYPE_2D)
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
}
vk::Cast(physicalDevice)->getImageFormatProperties(format, type, tiling, usage, flags, pImageFormatProperties);
return VK_SUCCESS;
} }
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties)
...@@ -3044,6 +2960,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(VkPhysi ...@@ -3044,6 +2960,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(VkPhysi
TRACE("(VkPhysicalDevice physicalDevice = %p, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo = %p, VkImageFormatProperties2* pImageFormatProperties = %p)", TRACE("(VkPhysicalDevice physicalDevice = %p, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo = %p, VkImageFormatProperties2* pImageFormatProperties = %p)",
physicalDevice, pImageFormatInfo, pImageFormatProperties); physicalDevice, pImageFormatInfo, pImageFormatProperties);
// "If the combination of parameters to vkGetPhysicalDeviceImageFormatProperties is not supported by the implementation
// for use in vkCreateImage, then all members of VkImageFormatProperties will be filled with zero."
memset(&pImageFormatProperties->imageFormatProperties, 0, sizeof(VkImageFormatProperties));
const VkBaseInStructure *extensionFormatInfo = reinterpret_cast<const VkBaseInStructure *>(pImageFormatInfo->pNext); const VkBaseInStructure *extensionFormatInfo = reinterpret_cast<const VkBaseInStructure *>(pImageFormatInfo->pNext);
const VkExternalMemoryHandleTypeFlagBits *handleType = nullptr; const VkExternalMemoryHandleTypeFlagBits *handleType = nullptr;
...@@ -3085,6 +3005,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(VkPhysi ...@@ -3085,6 +3005,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(VkPhysi
VkBaseOutStructure *extensionProperties = reinterpret_cast<VkBaseOutStructure *>(pImageFormatProperties->pNext); VkBaseOutStructure *extensionProperties = reinterpret_cast<VkBaseOutStructure *>(pImageFormatProperties->pNext);
#ifdef __ANDROID__
bool hasAHBUsage = false;
#endif
while(extensionProperties) while(extensionProperties)
{ {
switch(extensionProperties->sType) switch(extensionProperties->sType)
...@@ -3112,6 +3036,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(VkPhysi ...@@ -3112,6 +3036,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(VkPhysi
{ {
auto properties = reinterpret_cast<VkAndroidHardwareBufferUsageANDROID *>(extensionProperties); auto properties = reinterpret_cast<VkAndroidHardwareBufferUsageANDROID *>(extensionProperties);
vk::Cast(physicalDevice)->getProperties(properties); vk::Cast(physicalDevice)->getProperties(properties);
hasAHBUsage = true;
} }
break; break;
#endif #endif
...@@ -3123,13 +3048,119 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(VkPhysi ...@@ -3123,13 +3048,119 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(VkPhysi
extensionProperties = extensionProperties->pNext; extensionProperties = extensionProperties->pNext;
} }
return vkGetPhysicalDeviceImageFormatProperties(physicalDevice, VkFormat format = pImageFormatInfo->format;
pImageFormatInfo->format, VkImageType type = pImageFormatInfo->type;
pImageFormatInfo->type, VkImageTiling tiling = pImageFormatInfo->tiling;
pImageFormatInfo->tiling, VkImageUsageFlags usage = pImageFormatInfo->usage;
pImageFormatInfo->usage, VkImageCreateFlags flags = pImageFormatInfo->flags;
pImageFormatInfo->flags,
&(pImageFormatProperties->imageFormatProperties)); VkFormatProperties properties;
vk::PhysicalDevice::GetFormatProperties(format, &properties);
VkFormatFeatureFlags features;
switch(tiling)
{
case VK_IMAGE_TILING_LINEAR:
features = properties.linearTilingFeatures;
break;
case VK_IMAGE_TILING_OPTIMAL:
features = properties.optimalTilingFeatures;
break;
default:
UNSUPPORTED("VkImageTiling %d", int(tiling));
features = 0;
}
if(features == 0)
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
// Check for usage conflict with features
if((usage & VK_IMAGE_USAGE_SAMPLED_BIT) && !(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_STORAGE_BIT) && !(features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !(features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) && !(features & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) && !(features & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if((usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) && !(features & VK_FORMAT_FEATURE_TRANSFER_DST_BIT))
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
auto allRecognizedUsageBits = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
ASSERT(!(usage & ~(allRecognizedUsageBits)));
// "Images created with tiling equal to VK_IMAGE_TILING_LINEAR have further restrictions on their limits and capabilities
// compared to images created with tiling equal to VK_IMAGE_TILING_OPTIMAL."
if(tiling == VK_IMAGE_TILING_LINEAR)
{
if(type != VK_IMAGE_TYPE_2D)
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if(vk::Format(format).isDepth() || vk::Format(format).isStencil())
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
}
// "Images created with a format from one of those listed in Formats requiring sampler Y'CBCR conversion for VK_IMAGE_ASPECT_COLOR_BIT image views
// have further restrictions on their limits and capabilities compared to images created with other formats."
if(vk::Format(format).isYcbcrFormat())
{
if(type != VK_IMAGE_TYPE_2D)
{
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
}
vk::Cast(physicalDevice)->getImageFormatProperties(format, type, tiling, usage, flags, &pImageFormatProperties->imageFormatProperties);
#ifdef __ANDROID__
if(hasAHBUsage)
{
// AHardwareBuffer_lock may only be called with a single layer.
pImageFormatProperties->imageFormatProperties.maxArrayLayers = 1;
pImageFormatProperties->imageFormatProperties.maxMipLevels = 1;
}
#endif
return VK_SUCCESS;
} }
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties2 *pQueueFamilyProperties) VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties2 *pQueueFamilyProperties)
......
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