我正在开发一个 Android 应用程序,其中有一个
SurfaceTexture
绑定到 ExoPlayer 用于视频播放。纹理使用 GL_TEXTURE_EXTERNAL_OES
目标。我需要从此 VkImage
创建一个 Vulkan SurfaceTexture
,以便我可以使用 Vulkan 进行进一步渲染。
如何从使用
VkImage
的 SurfaceTexture
创建 GL_TEXTURE_EXTERNAL_OES
?我是否需要在此过程中使用特定的 Vulkan 扩展(如 VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
)?
要使用 GL_TEXTURE_EXTERNAL_OES 从 Android SurfaceTexture 创建 Vulkan VkImage,您需要利用 Android 的 AHardwareBuffer 和专为 Android 与 Vulkan 之间交互而设计的 Vulkan 扩展。一般方法包括从 SurfaceTexture 获取 AHardwareBuffer,然后使用 Vulkan 扩展 VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER 从缓冲区创建 VkImage。
使用说明如下:
CPP
#include <android/hardware_buffer.h>
#include <android/native_window.h>
// Assume `surfaceTexture` is your SurfaceTexture instance
ANativeWindow* nativeWindow = ANativeWindow_fromSurface(env,
surfaceTexture);
ANativeWindowBuffer* buffer;
nativeWindow->dequeueBuffer(nativeWindow, &buffer);
AHardwareBuffer* hardwareBuffer = buffer->handle;
CPP
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
externalMemoryImageCreateInfo.sType =
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
externalMemoryImageCreateInfo.handleTypes =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
创建 VkImageCreateInfo 结构:
您需要设置 VkImageCreateInfo 来创建 Vulkan 映像。
CPP
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.extent.width = ...; // Set width from your SurfaceTexture
imageCreateInfo.extent.height = ...; // Set height from your
SurfaceTexture
imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.format = ...; // Appropriate format matching the
`SurfaceTexture`
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.flags = 0;
imageCreateInfo.pNext = &externalMemoryImageCreateInfo;
创建 VkImage:
使用 VkImageCreateInfo 创建 VkImage。
CPP
VkImage vkImage;
VkResult result = vkCreateImage(device, &imageCreateInfo, nullptr,
&vkImage);
分配和绑定内存:
使用AHardwareBuffer为图像分配内存。 VkImportAndroidHardwareBufferInfoANDROID 结构体用于导入 AHardwareBuffer。
CPP
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(device, vkImage, &memoryRequirements);
VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
importHardwareBufferInfo.sType =
VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
importHardwareBufferInfo.buffer = hardwareBuffer;
VkMemoryAllocateInfo memoryAllocateInfo = {};
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memoryAllocateInfo.allocationSize = memoryRequirements.size;
memoryAllocateInfo.memoryTypeIndex = ...; // Find suitable memory type
memoryAllocateInfo.pNext = &importHardwareBufferInfo;
VkDeviceMemory deviceMemory;
result = vkAllocateMemory(device, &memoryAllocateInfo, nullptr,
&deviceMemory);
vkBindImageMemory(device, vkImage, deviceMemory, 0);
关键扩展和注意事项: VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER:这对于从 AHardwareBuffer 创建 VkImage 至关重要。 AHardwareBuffer:支持 SurfaceTexture 的底层缓冲区,可用于 Vulkan 互操作。 同步:确保跨不同 API(OpenGL ES 和 Vulkan)访问缓冲区时正确同步。 这种方法允许您从 SurfaceTexture 创建 Vulkan VkImage 并使用 Vulkan 进行进一步的渲染操作。