12 changed files with 424 additions and 20 deletions
-
55src/android/app/src/main/java/org/yuzu/yuzu_emu/media/NativeMediaCodec.java
-
1src/video_core/CMakeLists.txt
-
18src/video_core/host1x/ffmpeg/mediacodec_bridge.h
-
83src/video_core/host1x/ffmpeg/mediacodec_bridge_android.cpp
-
109src/video_core/renderer_vulkan/vk_present_manager.cpp
-
10src/video_core/renderer_vulkan/vk_present_manager.h
-
116src/video_core/vulkan_common/ahardwarebuffer_vulkan.cpp
-
23src/video_core/vulkan_common/ahardwarebuffer_vulkan.h
-
17src/video_core/vulkan_common/vulkan_device.cpp
-
6src/video_core/vulkan_common/vulkan_device.h
-
3src/video_core/vulkan_common/vulkan_wrapper.cpp
-
3src/video_core/vulkan_common/vulkan_wrapper.h
@ -0,0 +1,116 @@ |
|||
#ifdef __ANDROID__
|
|||
|
|||
#include "ahardwarebuffer_vulkan.h"
|
|||
#include <vulkan/vulkan.h>
|
|||
#include <vulkan/vk_android_external_memory_android_hardware_buffer.h>
|
|||
#include <android/hardware_buffer.h>
|
|||
#include <cstring>
|
|||
|
|||
namespace { |
|||
|
|||
static uint32_t FindMemoryTypeIndex(VkPhysicalDevice physicalDevice, uint32_t typeBits, |
|||
VkMemoryPropertyFlags properties) { |
|||
VkPhysicalDeviceMemoryProperties memProps; |
|||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); |
|||
for (uint32_t i = 0; i < memProps.memoryTypeCount; ++i) { |
|||
if ((typeBits & (1u << i)) && (memProps.memoryTypes[i].propertyFlags & properties) == properties) { |
|||
return i; |
|||
} |
|||
} |
|||
// Fallback: return first matching bit
|
|||
for (uint32_t i = 0; i < memProps.memoryTypeCount; ++i) { |
|||
if (typeBits & (1u << i)) return i; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
} // anonymous
|
|||
|
|||
static bool ImportAHardwareBufferInternal(PFN_vkGetAndroidHardwareBufferPropertiesANDROID get_props, |
|||
VkDevice device, VkPhysicalDevice physicalDevice, AHardwareBuffer* ahb, |
|||
VkImage* outImage, VkDeviceMemory* outMemory, VkFormat* outFormat) { |
|||
if (!device || !physicalDevice || !ahb || !outImage || !outMemory || !get_props) return false; |
|||
|
|||
VkAndroidHardwareBufferPropertiesANDROID ahb_props{}; |
|||
ahb_props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; |
|||
VkResult r = get_props(device, ahb, &ahb_props); |
|||
if (r != VK_SUCCESS) return false; |
|||
|
|||
// Determine VkFormat to use
|
|||
VkFormat fmt = static_cast<VkFormat>(ahb_props.format); |
|||
if (outFormat) *outFormat = fmt; |
|||
|
|||
// Create image with external memory
|
|||
VkExternalMemoryImageCreateInfo external_info{}; |
|||
external_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; |
|||
external_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; |
|||
|
|||
VkImageCreateInfo image_info{}; |
|||
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; |
|||
image_info.pNext = &external_info; |
|||
image_info.imageType = VK_IMAGE_TYPE_2D; |
|||
image_info.format = fmt; |
|||
image_info.extent.width = ahb_props.allocationSize ? 0 : 0; // placeholder; we'll query via AHardwareBuffer_describe
|
|||
|
|||
AHardwareBuffer_Desc desc; |
|||
AHardwareBuffer_describe(ahb, &desc); |
|||
image_info.extent.width = desc.width; |
|||
image_info.extent.height = desc.height; |
|||
image_info.extent.depth = 1; |
|||
image_info.mipLevels = 1; |
|||
image_info.arrayLayers = 1; |
|||
image_info.samples = VK_SAMPLE_COUNT_1_BIT; |
|||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
|||
// Use typical usage bits; adjust as needed by consumer
|
|||
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
|||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
|||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
|||
|
|||
r = vkCreateImage(device, &image_info, nullptr, outImage); |
|||
if (r != VK_SUCCESS) return false; |
|||
|
|||
VkMemoryRequirements memReq; |
|||
vkGetImageMemoryRequirements(device, *outImage, &memReq); |
|||
|
|||
// Prepare import struct
|
|||
VkImportAndroidHardwareBufferInfoANDROID import_info{}; |
|||
import_info.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; |
|||
import_info.buffer = ahb; |
|||
|
|||
VkMemoryAllocateInfo alloc_info{}; |
|||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; |
|||
alloc_info.pNext = &import_info; |
|||
alloc_info.allocationSize = memReq.size; |
|||
alloc_info.memoryTypeIndex = FindMemoryTypeIndex(physicalDevice, memReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); |
|||
|
|||
r = vkAllocateMemory(device, &alloc_info, nullptr, outMemory); |
|||
if (r != VK_SUCCESS) { |
|||
vkDestroyImage(device, *outImage, nullptr); |
|||
return false; |
|||
} |
|||
|
|||
r = vkBindImageMemory(device, *outImage, *outMemory, 0); |
|||
if (r != VK_SUCCESS) { |
|||
vkDestroyImage(device, *outImage, nullptr); |
|||
vkFreeMemory(device, *outMemory, nullptr); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
bool ImportAHardwareBufferToVk(VkDevice device, VkPhysicalDevice physicalDevice, AHardwareBuffer* ahb, |
|||
VkImage* outImage, VkDeviceMemory* outMemory, VkFormat* outFormat) { |
|||
PFN_vkGetAndroidHardwareBufferPropertiesANDROID fpGetAHBProps = |
|||
(PFN_vkGetAndroidHardwareBufferPropertiesANDROID)vkGetDeviceProcAddr(device, "vkGetAndroidHardwareBufferPropertiesANDROID"); |
|||
return ImportAHardwareBufferInternal(fpGetAHBProps, device, physicalDevice, ahb, outImage, outMemory, outFormat); |
|||
} |
|||
|
|||
bool ImportAHardwareBufferToVk(const Vulkan::vk::DeviceDispatch& dld, |
|||
VkDevice device, VkPhysicalDevice physicalDevice, AHardwareBuffer* ahb, |
|||
VkImage* outImage, VkDeviceMemory* outMemory, VkFormat* outFormat) { |
|||
return ImportAHardwareBufferInternal(dld.vkGetAndroidHardwareBufferPropertiesANDROID, device, physicalDevice, ahb, |
|||
outImage, outMemory, outFormat); |
|||
} |
|||
|
|||
#endif // __ANDROID__
|
|||
@ -0,0 +1,23 @@ |
|||
#pragma once |
|||
|
|||
#ifdef __ANDROID__ |
|||
|
|||
#include <vulkan/vulkan.h> |
|||
#include <android/hardware_buffer.h> |
|||
#include "video_core/vulkan_common/vulkan_wrapper.h" |
|||
|
|||
// Import an AHardwareBuffer into Vulkan as a VkImage with bound memory. |
|||
// On success returns true and fills outImage/outMemory/outFormat. Caller is responsible |
|||
// for destroying the VkImage and freeing the VkDeviceMemory when done. The AHardwareBuffer |
|||
// reference is not released by this function; caller should call AHardwareBuffer_release when |
|||
// done with the AHardwareBuffer. |
|||
|
|||
bool ImportAHardwareBufferToVk(VkDevice device, VkPhysicalDevice physicalDevice, AHardwareBuffer* ahb, |
|||
VkImage* outImage, VkDeviceMemory* outMemory, VkFormat* outFormat); |
|||
|
|||
// Overload that uses the dispatch loader for extension calls. |
|||
bool ImportAHardwareBufferToVk(const Vulkan::vk::DeviceDispatch& dld, |
|||
VkDevice device, VkPhysicalDevice physicalDevice, AHardwareBuffer* ahb, |
|||
VkImage* outImage, VkDeviceMemory* outMemory, VkFormat* outFormat); |
|||
|
|||
#endif // __ANDROID__ |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue