Skip to content

Commit 244dbe4

Browse files
Extract GPDIFP2 getProducerUsage path to seperate function
Extracting the GPDIFP2 logic to its own function makes it easier to exit early from the GPDIFP2 path when we need to fall back to the GetSwapchainGrallocUsage*ANDROID path. This change also fixes an issue where we would exit getProducerUsage early instead of falling back to the gralloc paths if GPDIFP2 would return an error when called with an unsupported format. Bug: 379230826 Test: atest libvulkan_test Flag: EXEMPT bugfix Change-Id: I42f1fe31e5e4a01c472a12854a1f4e989d2786dc
1 parent 9fd5fdd commit 244dbe4

5 files changed

Lines changed: 224 additions & 105 deletions

File tree

vulkan/libvulkan/Android.bp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ package {
2222
default_applicable_licenses: ["frameworks_native_license"],
2323
}
2424

25+
// Expose internal header files to test testing binary
26+
cc_library_headers {
27+
name: "libvulkanprivate_headers-testing",
28+
export_include_dirs: ["."],
29+
visibility: ["//frameworks/native/vulkan/tests"],
30+
}
31+
2532
ndk_library {
2633
name: "libvulkan",
2734
symbol_file: "libvulkan.map.txt",

vulkan/libvulkan/TEST_MAPPING

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"presubmit": [
3+
{
4+
"name": "libvulkan_test"
5+
}
6+
]
7+
}

vulkan/libvulkan/swapchain.cpp

Lines changed: 119 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,115 +1413,138 @@ static void DestroySwapchainInternal(VkDevice device,
14131413
allocator->pfnFree(allocator->pUserData, swapchain);
14141414
}
14151415

1416-
static VkResult getProducerUsage(const VkDevice& device,
1417-
const VkSwapchainCreateInfoKHR* create_info,
1418-
const VkSwapchainImageUsageFlagsANDROID swapchain_image_usage,
1419-
bool create_protected_swapchain,
1420-
uint64_t* producer_usage) {
1421-
// Get the physical device to query the appropriate producer usage
1422-
const VkPhysicalDevice& pdev = GetData(device).driver_physical_device;
1423-
const InstanceData& instance_data = GetData(pdev);
1424-
const InstanceDriverTable& instance_dispatch = instance_data.driver;
1425-
if (instance_dispatch.GetPhysicalDeviceImageFormatProperties2 ||
1426-
instance_dispatch.GetPhysicalDeviceImageFormatProperties2KHR) {
1427-
// Look through the create_info pNext chain passed to createSwapchainKHR
1428-
// for an image compression control struct.
1429-
// if one is found AND the appropriate extensions are enabled, create a
1430-
// VkImageCompressionControlEXT structure to pass on to
1431-
// GetPhysicalDeviceImageFormatProperties2
1432-
void* compression_control_pNext = nullptr;
1433-
VkImageCompressionControlEXT image_compression = {};
1434-
const VkSwapchainCreateInfoKHR* create_infos = create_info;
1435-
while (create_infos->pNext) {
1436-
create_infos = reinterpret_cast<const VkSwapchainCreateInfoKHR*>(create_infos->pNext);
1437-
switch (create_infos->sType) {
1438-
case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: {
1439-
const VkImageCompressionControlEXT* compression_infos =
1440-
reinterpret_cast<const VkImageCompressionControlEXT*>(create_infos);
1441-
image_compression = *compression_infos;
1442-
image_compression.pNext = nullptr;
1443-
compression_control_pNext = &image_compression;
1444-
} break;
1445-
default:
1446-
// Ignore all other info structs
1447-
break;
1448-
}
1416+
static VkResult getProducerUsageGPDIFP2(
1417+
const VkPhysicalDevice& pdev,
1418+
const VkSwapchainCreateInfoKHR* create_info,
1419+
const VkSwapchainImageUsageFlagsANDROID swapchain_image_usage,
1420+
bool create_protected_swapchain,
1421+
uint64_t* producer_usage) {
1422+
// Look through the create_info pNext chain passed to createSwapchainKHR
1423+
// for an image compression control struct.
1424+
// if one is found AND the appropriate extensions are enabled, create a
1425+
// VkImageCompressionControlEXT structure to pass on to
1426+
// GetPhysicalDeviceImageFormatProperties2
1427+
void* compression_control_pNext = nullptr;
1428+
VkImageCompressionControlEXT image_compression = {};
1429+
const VkSwapchainCreateInfoKHR* create_infos = create_info;
1430+
while (create_infos->pNext) {
1431+
create_infos = reinterpret_cast<const VkSwapchainCreateInfoKHR*>(
1432+
create_infos->pNext);
1433+
switch (create_infos->sType) {
1434+
case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: {
1435+
const VkImageCompressionControlEXT* compression_infos =
1436+
reinterpret_cast<const VkImageCompressionControlEXT*>(
1437+
create_infos);
1438+
image_compression = *compression_infos;
1439+
image_compression.pNext = nullptr;
1440+
compression_control_pNext = &image_compression;
1441+
} break;
1442+
default:
1443+
// Ignore all other info structs
1444+
break;
14491445
}
1446+
}
14501447

1451-
// call GetPhysicalDeviceImageFormatProperties2KHR
1452-
VkPhysicalDeviceExternalImageFormatInfo external_image_format_info = {
1453-
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
1454-
.pNext = compression_control_pNext,
1455-
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
1456-
};
1448+
// call GetPhysicalDeviceImageFormatProperties2KHR
1449+
VkPhysicalDeviceExternalImageFormatInfo external_image_format_info = {
1450+
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
1451+
.pNext = compression_control_pNext,
1452+
.handleType =
1453+
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
1454+
};
14571455

1458-
// AHB does not have an sRGB format so we can't pass it to GPDIFP
1459-
// We need to convert the format to unorm if it is srgb
1460-
VkFormat format = create_info->imageFormat;
1461-
if (format == VK_FORMAT_R8G8B8A8_SRGB) {
1462-
format = VK_FORMAT_R8G8B8A8_UNORM;
1463-
}
1456+
// AHB does not have an sRGB format so we can't pass it to GPDIFP
1457+
// We need to convert the format to unorm if it is srgb
1458+
VkFormat format = create_info->imageFormat;
1459+
if (format == VK_FORMAT_R8G8B8A8_SRGB) {
1460+
format = VK_FORMAT_R8G8B8A8_UNORM;
1461+
}
14641462

1465-
VkPhysicalDeviceImageFormatInfo2 image_format_info = {
1466-
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
1467-
.pNext = &external_image_format_info,
1468-
.format = format,
1469-
.type = VK_IMAGE_TYPE_2D,
1470-
.tiling = VK_IMAGE_TILING_OPTIMAL,
1471-
.usage = create_info->imageUsage,
1472-
.flags = create_protected_swapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
1473-
};
1463+
VkPhysicalDeviceImageFormatInfo2 image_format_info = {
1464+
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
1465+
.pNext = &external_image_format_info,
1466+
.format = format,
1467+
.type = VK_IMAGE_TYPE_2D,
1468+
.tiling = VK_IMAGE_TILING_OPTIMAL,
1469+
.usage = create_info->imageUsage,
1470+
.flags =
1471+
create_protected_swapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
1472+
};
14741473

1475-
// If supporting mutable format swapchain add the mutable format flag
1476-
if (create_info->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
1477-
image_format_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
1478-
image_format_info.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
1479-
}
1474+
// If supporting mutable format swapchain add the mutable format flag
1475+
if (create_info->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
1476+
image_format_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
1477+
image_format_info.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
1478+
}
14801479

1481-
VkAndroidHardwareBufferUsageANDROID ahb_usage;
1482-
ahb_usage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
1483-
ahb_usage.pNext = nullptr;
1480+
VkAndroidHardwareBufferUsageANDROID ahb_usage;
1481+
ahb_usage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
1482+
ahb_usage.pNext = nullptr;
14841483

1485-
VkImageFormatProperties2 image_format_properties;
1486-
image_format_properties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
1487-
image_format_properties.pNext = &ahb_usage;
1484+
VkImageFormatProperties2 image_format_properties;
1485+
image_format_properties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
1486+
image_format_properties.pNext = &ahb_usage;
14881487

1489-
VkResult result = GetPhysicalDeviceImageFormatProperties2(
1490-
pdev, &image_format_info, &image_format_properties);
1491-
if (result != VK_SUCCESS) {
1492-
ALOGE(
1493-
"VkGetPhysicalDeviceImageFormatProperties2 for AHB usage "
1494-
"failed: %d",
1495-
result);
1496-
return VK_ERROR_SURFACE_LOST_KHR;
1497-
}
1488+
VkResult result = GetPhysicalDeviceImageFormatProperties2(
1489+
pdev, &image_format_info, &image_format_properties);
1490+
if (result != VK_SUCCESS) {
1491+
ALOGE(
1492+
"VkGetPhysicalDeviceImageFormatProperties2 for AHB usage "
1493+
"failed: %d",
1494+
result);
1495+
return VK_ERROR_SURFACE_LOST_KHR;
1496+
}
1497+
// Determine if USAGE_FRONT_BUFFER is needed.
1498+
// GPDIFP2 has no means of using VkSwapchainImageUsageFlagsANDROID when
1499+
// querying for producer_usage. So androidHardwareBufferUsage will not
1500+
// contain USAGE_FRONT_BUFFER. We need to manually check for usage here.
1501+
if (!(swapchain_image_usage &
1502+
VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)) {
1503+
*producer_usage = ahb_usage.androidHardwareBufferUsage;
1504+
return VK_SUCCESS;
1505+
}
14981506

1499-
// Determine if USAGE_FRONT_BUFFER is needed.
1500-
// GPDIFP2 has no means of using VkSwapchainImageUsageFlagsANDROID when
1501-
// querying for producer_usage. So androidHardwareBufferUsage will not
1502-
// contain USAGE_FRONT_BUFFER. We need to manually check for usage here.
1503-
if (!(swapchain_image_usage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)) {
1504-
*producer_usage = ahb_usage.androidHardwareBufferUsage;
1505-
return VK_SUCCESS;
1506-
}
1507+
// Check if USAGE_FRONT_BUFFER is supported for this swapchain
1508+
AHardwareBuffer_Desc ahb_desc = {
1509+
.width = create_info->imageExtent.width,
1510+
.height = create_info->imageExtent.height,
1511+
.layers = create_info->imageArrayLayers,
1512+
.format = create_info->imageFormat,
1513+
.usage = ahb_usage.androidHardwareBufferUsage |
1514+
AHARDWAREBUFFER_USAGE_FRONT_BUFFER,
1515+
.stride = 0, // stride is always ignored when calling isSupported()
1516+
};
15071517

1508-
// Check if USAGE_FRONT_BUFFER is supported for this swapchain
1509-
AHardwareBuffer_Desc ahb_desc = {
1510-
.width = create_info->imageExtent.width,
1511-
.height = create_info->imageExtent.height,
1512-
.layers = create_info->imageArrayLayers,
1513-
.format = create_info->imageFormat,
1514-
.usage = ahb_usage.androidHardwareBufferUsage | AHARDWAREBUFFER_USAGE_FRONT_BUFFER,
1515-
.stride = 0, // stride is always ignored when calling isSupported()
1516-
};
1518+
// If FRONT_BUFFER is not supported in the GPDIFP2 path
1519+
// then we need to fallback to GetSwapchainGrallocUsageXAndroid
1520+
if (AHardwareBuffer_isSupported(&ahb_desc)) {
1521+
*producer_usage = ahb_usage.androidHardwareBufferUsage;
1522+
*producer_usage |= AHARDWAREBUFFER_USAGE_FRONT_BUFFER;
1523+
return VK_SUCCESS;
1524+
}
1525+
1526+
return VK_ERROR_FORMAT_NOT_SUPPORTED;
1527+
}
1528+
1529+
static VkResult getProducerUsage(const VkDevice& device,
1530+
const VkSwapchainCreateInfoKHR* create_info,
1531+
const VkSwapchainImageUsageFlagsANDROID swapchain_image_usage,
1532+
bool create_protected_swapchain,
1533+
uint64_t* producer_usage) {
1534+
// Get the physical device to query the appropriate producer usage
1535+
const VkPhysicalDevice& pdev = GetData(device).driver_physical_device;
1536+
const InstanceData& instance_data = GetData(pdev);
1537+
const InstanceDriverTable& instance_dispatch = instance_data.driver;
15171538

1518-
// If FRONT_BUFFER is not supported,
1519-
// then we need to call GetSwapchainGrallocUsageXAndroid below
1520-
if (AHardwareBuffer_isSupported(&ahb_desc)) {
1521-
*producer_usage = ahb_usage.androidHardwareBufferUsage;
1522-
*producer_usage |= AHARDWAREBUFFER_USAGE_FRONT_BUFFER;
1539+
if (instance_dispatch.GetPhysicalDeviceImageFormatProperties2 ||
1540+
instance_dispatch.GetPhysicalDeviceImageFormatProperties2KHR) {
1541+
VkResult result =
1542+
getProducerUsageGPDIFP2(pdev, create_info, swapchain_image_usage,
1543+
create_protected_swapchain, producer_usage);
1544+
if (result == VK_SUCCESS) {
15231545
return VK_SUCCESS;
15241546
}
1547+
// Fall through to gralloc path on error
15251548
}
15261549

15271550
uint64_t native_usage = 0;

vulkan/tests/Android.bp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ cc_test {
2727

2828
header_libs: [
2929
"hwvulkan_headers",
30+
"libvulkanprivate_headers-testing",
3031
"vulkan_headers",
3132
],
3233

vulkan/tests/libvulkan_test.cpp

Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#include <android/log.h>
18+
#include <driver.h>
1819
#include <gmock/gmock.h>
1920
#include <gtest/gtest.h>
2021
#include <media/NdkImageReader.h>
@@ -29,6 +30,8 @@
2930

3031
namespace android {
3132

33+
namespace libvulkantest {
34+
3235
class AImageReaderVulkanSwapchainTest : public ::testing::Test {
3336
public:
3437
AImageReaderVulkanSwapchainTest() {}
@@ -271,17 +274,20 @@ class AImageReaderVulkanSwapchainTest : public ::testing::Test {
271274

272275
VkResult res =
273276
vkCreateSwapchainKHR(mDevice, &swapchainInfo, nullptr, &mSwapchain);
274-
VK_CHECK(res);
275-
LOGI("Swapchain created successfully");
277+
if (res == VK_SUCCESS) {
278+
LOGI("Swapchain created successfully");
276279

277-
uint32_t swapchainImageCount = 0;
278-
vkGetSwapchainImagesKHR(mDevice, mSwapchain, &swapchainImageCount,
279-
nullptr);
280-
std::vector<VkImage> swapchainImages(swapchainImageCount);
281-
vkGetSwapchainImagesKHR(mDevice, mSwapchain, &swapchainImageCount,
282-
swapchainImages.data());
280+
uint32_t swapchainImageCount = 0;
281+
vkGetSwapchainImagesKHR(mDevice, mSwapchain, &swapchainImageCount,
282+
nullptr);
283+
std::vector<VkImage> swapchainImages(swapchainImageCount);
284+
vkGetSwapchainImagesKHR(mDevice, mSwapchain, &swapchainImageCount,
285+
swapchainImages.data());
283286

284-
LOGI("Swapchain has %u images", swapchainImageCount);
287+
LOGI("Swapchain has %u images", swapchainImageCount);
288+
} else {
289+
LOGI("Swapchain creation failed");
290+
}
285291
}
286292

287293
// Image available callback (AImageReader)
@@ -357,4 +363,79 @@ TEST_F(AImageReaderVulkanSwapchainTest, TestHelperMethods) {
357363
cleanUpSwapchainForTest();
358364
}
359365

366+
// Passing state in these tests requires global state. Wrap each test in an
367+
// anonymous namespace to prevent conflicting names.
368+
namespace {
369+
370+
VKAPI_ATTR VkResult VKAPI_CALL hookedGetPhysicalDeviceImageFormatProperties2KHR(
371+
VkPhysicalDevice,
372+
const VkPhysicalDeviceImageFormatInfo2*,
373+
VkImageFormatProperties2*) {
374+
return VK_ERROR_SURFACE_LOST_KHR;
375+
}
376+
377+
static PFN_vkGetSwapchainGrallocUsage2ANDROID
378+
pfnNextGetSwapchainGrallocUsage2ANDROID = nullptr;
379+
380+
static bool g_grallocCalled = false;
381+
382+
VKAPI_ATTR VkResult VKAPI_CALL hookGetSwapchainGrallocUsage2ANDROID(
383+
VkDevice device,
384+
VkFormat format,
385+
VkImageUsageFlags imageUsage,
386+
VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
387+
uint64_t* grallocConsumerUsage,
388+
uint64_t* grallocProducerUsage) {
389+
g_grallocCalled = true;
390+
if (pfnNextGetSwapchainGrallocUsage2ANDROID) {
391+
return pfnNextGetSwapchainGrallocUsage2ANDROID(
392+
device, format, imageUsage, swapchainImageUsage,
393+
grallocConsumerUsage, grallocProducerUsage);
394+
}
395+
396+
return VK_ERROR_INITIALIZATION_FAILED;
397+
}
398+
399+
TEST_F(AImageReaderVulkanSwapchainTest, getProducerUsageFallbackTest1) {
400+
// BUG: 379230826
401+
// Verify that getProducerUsage falls back to
402+
// GetSwapchainGrallocUsage*ANDROID if GPDIFP2 fails
403+
std::vector<const char*> instanceLayers = {};
404+
std::vector<const char*> deviceLayers = {};
405+
createVulkanInstance(instanceLayers);
406+
407+
createAImageReader(640, 480, AIMAGE_FORMAT_PRIVATE, 3);
408+
getANativeWindowFromReader();
409+
createVulkanSurface();
410+
pickPhysicalDeviceAndQueueFamily();
411+
412+
createDeviceAndGetQueue(deviceLayers);
413+
auto& pdev = vulkan::driver::GetData(mDevice).driver_physical_device;
414+
auto& pdevDispatchTable = vulkan::driver::GetData(pdev).driver;
415+
auto& deviceDispatchTable = vulkan::driver::GetData(mDevice).driver;
416+
417+
ASSERT_NE(deviceDispatchTable.GetSwapchainGrallocUsage2ANDROID, nullptr);
418+
419+
pdevDispatchTable.GetPhysicalDeviceImageFormatProperties2 =
420+
hookedGetPhysicalDeviceImageFormatProperties2KHR;
421+
deviceDispatchTable.GetSwapchainGrallocUsage2ANDROID =
422+
hookGetSwapchainGrallocUsage2ANDROID;
423+
424+
ASSERT_FALSE(g_grallocCalled);
425+
426+
createSwapchain();
427+
428+
ASSERT_TRUE(g_grallocCalled);
429+
430+
ASSERT_NE(mVkInstance, (VkInstance)VK_NULL_HANDLE);
431+
ASSERT_NE(mPhysicalDev, (VkPhysicalDevice)VK_NULL_HANDLE);
432+
ASSERT_NE(mDevice, (VkDevice)VK_NULL_HANDLE);
433+
ASSERT_NE(mSurface, (VkSurfaceKHR)VK_NULL_HANDLE);
434+
cleanUpSwapchainForTest();
435+
}
436+
437+
} // namespace
438+
439+
} // namespace libvulkantest
440+
360441
} // namespace android

0 commit comments

Comments
 (0)