|
|
|
|
|
|
#include "src/shell/common/shell_io_manager.h"
|
|
|
|
#include "src/shell/gpu/gpu_surface_delegate.h"
|
|
|
|
#include "src/shell/gpu/gpu_surface_gl_delegate.h"
|
|
|
|
|
|
|
|
#define UNITY_USED_VULKAN_API_FUNCTIONS(apply) \
|
|
|
|
apply(vkGetDeviceProcAddr); \ |
|
|
|
apply(vkCreateInstance); \ |
|
|
|
apply(vkCmdBeginRenderPass); \ |
|
|
|
apply(vkCreateBuffer); \ |
|
|
|
apply(vkGetPhysicalDeviceMemoryProperties); \ |
|
|
|
apply(vkGetBufferMemoryRequirements); \ |
|
|
|
apply(vkMapMemory); \ |
|
|
|
apply(vkBindBufferMemory); \ |
|
|
|
apply(vkAllocateMemory); \ |
|
|
|
apply(vkDestroyBuffer); \ |
|
|
|
apply(vkFreeMemory); \ |
|
|
|
apply(vkUnmapMemory); \ |
|
|
|
apply(vkQueueWaitIdle); \ |
|
|
|
apply(vkDeviceWaitIdle); \ |
|
|
|
apply(vkCmdCopyBufferToImage); \ |
|
|
|
apply(vkFlushMappedMemoryRanges); \ |
|
|
|
apply(vkCreatePipelineLayout); \ |
|
|
|
apply(vkCreateShaderModule); \ |
|
|
|
apply(vkDestroyShaderModule); \ |
|
|
|
apply(vkCreateGraphicsPipelines); \ |
|
|
|
apply(vkCmdBindPipeline); \ |
|
|
|
apply(vkCmdDraw); \ |
|
|
|
apply(vkCmdPushConstants); \ |
|
|
|
apply(vkCmdBindVertexBuffers); \ |
|
|
|
apply(vkDestroyPipeline); \ |
|
|
|
apply(vkGetAndroidHardwareBufferPropertiesANDROID); \ |
|
|
|
apply(vkDestroyPipelineLayout); |
|
|
|
|
|
|
|
#define VULKAN_DEFINE_API_FUNCPTR(func) static PFN_##func my_##func
|
|
|
|
VULKAN_DEFINE_API_FUNCPTR(vkGetInstanceProcAddr); |
|
|
|
UNITY_USED_VULKAN_API_FUNCTIONS(VULKAN_DEFINE_API_FUNCPTR); |
|
|
|
#undef VULKAN_DEFINE_API_FUNCPTR
|
|
|
|
|
|
|
|
static void LoadVulkanAPI(PFN_vkGetInstanceProcAddr getInstanceProcAddr, |
|
|
|
VkInstance instance) |
|
|
|
{ |
|
|
|
if (!my_vkGetInstanceProcAddr && getInstanceProcAddr) |
|
|
|
my_vkGetInstanceProcAddr = getInstanceProcAddr; |
|
|
|
|
|
|
|
if (!my_vkCreateInstance) |
|
|
|
my_vkCreateInstance = (PFN_vkCreateInstance)my_vkGetInstanceProcAddr( |
|
|
|
VK_NULL_HANDLE, "vkCreateInstance"); |
|
|
|
|
|
|
|
#define LOAD_VULKAN_FUNC(fn) \
|
|
|
|
if (!my_##fn) \ |
|
|
|
my_##fn = (PFN_##fn)my_vkGetInstanceProcAddr(instance, #fn) |
|
|
|
UNITY_USED_VULKAN_API_FUNCTIONS(LOAD_VULKAN_FUNC); |
|
|
|
#undef LOAD_VULKAN_FUNC
|
|
|
|
} |
|
|
|
|
|
|
|
static bool getMemoryTypeIndex(uint32_t typeBits, VkPhysicalDevice device, VkFlags quirementsMaks, |
|
|
|
uint32_t &index) |
|
|
|
{ |
|
|
|
// const auto& memoryPropertys =
|
|
|
|
// VulkanManager::Get().physical->mempryProperties;
|
|
|
|
VkPhysicalDeviceMemoryProperties memoryPropertys; |
|
|
|
vkGetPhysicalDeviceMemoryProperties(device, &memoryPropertys); |
|
|
|
for (uint32_t i = 0; i < memoryPropertys.memoryTypeCount; i++) |
|
|
|
{ |
|
|
|
if ((typeBits & 1) == 1) |
|
|
|
{ |
|
|
|
// Type is available, does it match user properties?
|
|
|
|
if ((memoryPropertys.memoryTypes[i].propertyFlags & |
|
|
|
quirementsMaks) == quirementsMaks) |
|
|
|
{ |
|
|
|
index = i; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
typeBits >>= 1; |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
namespace uiwidgets |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
buffer = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
usage.width = width; //format.width;
|
|
|
|
usage.width = width; //format.width;
|
|
|
|
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER | |
|
|
|
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; |
|
|
|
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER | |
|
|
|
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; |
|
|
|
|
|
|
|
|
|
|
|
if (m_UnityVulkan != nullptr) |
|
|
|
{ |
|
|
|
auto vkDevice = m_Instance.device; |
|
|
|
// auto memoryPropertys = m_Instance.memoryTypeIndex;
|
|
|
|
// VkImage vkImage;
|
|
|
|
bool useExternalFormat = true; |
|
|
|
|
|
|
|
VkResult err; |
|
|
|
|
|
|
|
AHardwareBuffer_Desc bufferDesc; |
|
|
|
AHardwareBuffer_describe(buffer, &bufferDesc); |
|
|
|
|
|
|
|
VkAndroidHardwareBufferFormatPropertiesANDROID formatInfo = { |
|
|
|
.sType = |
|
|
|
VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, |
|
|
|
.pNext = nullptr, |
|
|
|
}; |
|
|
|
VkAndroidHardwareBufferPropertiesANDROID properties = { |
|
|
|
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, |
|
|
|
.pNext = &formatInfo, |
|
|
|
}; |
|
|
|
err = vkGetAndroidHardwareBufferPropertiesANDROID(vkDevice, buffer, &properties); |
|
|
|
|
|
|
|
VkExternalFormatANDROID externalFormat{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, |
|
|
|
.pNext = nullptr, |
|
|
|
.externalFormat = formatInfo.externalFormat, |
|
|
|
}; |
|
|
|
VkExternalMemoryImageCreateInfo externalCreateInfo{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, |
|
|
|
.pNext = &externalFormat, |
|
|
|
.handleTypes = |
|
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
VkImageCreateInfo imageInfo = {}; |
|
|
|
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; |
|
|
|
imageInfo.pNext = &externalCreateInfo; |
|
|
|
imageInfo.flags = 0; |
|
|
|
imageInfo.imageType = VK_IMAGE_TYPE_2D; |
|
|
|
imageInfo.format = |
|
|
|
VK_FORMAT_UNDEFINED; |
|
|
|
imageInfo.extent = { |
|
|
|
bufferDesc.width, |
|
|
|
bufferDesc.height, |
|
|
|
1, |
|
|
|
}; |
|
|
|
imageInfo.mipLevels = 1, imageInfo.arrayLayers = 1; |
|
|
|
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; |
|
|
|
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; |
|
|
|
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
|
|
|
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
|
|
|
imageInfo.queueFamilyIndexCount = 0; |
|
|
|
imageInfo.pQueueFamilyIndices = nullptr; |
|
|
|
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
|
|
|
auto result = vkCreateImage(vkDevice, &imageInfo, nullptr, &vk_Image_); |
|
|
|
|
|
|
|
VkImportAndroidHardwareBufferInfoANDROID androidHardwareBufferInfo{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, |
|
|
|
.pNext = nullptr, |
|
|
|
.buffer = buffer, |
|
|
|
}; |
|
|
|
VkMemoryDedicatedAllocateInfo memoryAllocateInfo{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, |
|
|
|
.pNext = &androidHardwareBufferInfo, |
|
|
|
.image = vk_Image_, |
|
|
|
.buffer = VK_NULL_HANDLE, |
|
|
|
}; |
|
|
|
// android的hardbuffer位置(properties)
|
|
|
|
VkMemoryRequirements requires; |
|
|
|
vkGetImageMemoryRequirements(vkDevice, vk_Image_, &requires); |
|
|
|
|
|
|
|
uint32_t memoryTypeIndex = 0; |
|
|
|
bool getIndex = |
|
|
|
getMemoryTypeIndex(properties.memoryTypeBits, m_Instance.physicalDevice, 0, memoryTypeIndex); |
|
|
|
assert(getIndex); |
|
|
|
|
|
|
|
VkMemoryAllocateInfo memoryInfo = {}; |
|
|
|
memoryInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; |
|
|
|
memoryInfo.pNext = &memoryAllocateInfo; |
|
|
|
memoryInfo.memoryTypeIndex = memoryTypeIndex; |
|
|
|
memoryInfo.allocationSize = properties.allocationSize; |
|
|
|
|
|
|
|
auto al = vkAllocateMemory(vkDevice, &memoryInfo, nullptr, &memory); |
|
|
|
|
|
|
|
VkBindImageMemoryInfo bindImageInfo; |
|
|
|
bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; |
|
|
|
bindImageInfo.pNext = nullptr; |
|
|
|
bindImageInfo.image = vk_Image_; |
|
|
|
bindImageInfo.memory = memory; |
|
|
|
bindImageInfo.memoryOffset = 0; |
|
|
|
// vkBindImageMemory2KHR(vkDevice, 1, &bindImageInfo);
|
|
|
|
vkBindImageMemory2(vkDevice, 1, &bindImageInfo); |
|
|
|
} |
|
|
|
|
|
|
|
EGLClientBuffer native_buffer = eglGetNativeClientBufferANDROID(buffer); |
|
|
|
assert(native_buffer); |
|
|
|
auto success = false; |
|
|
|
|
|
|
EGL_NATIVE_BUFFER_ANDROID, native_buffer, attrs); |
|
|
|
EGL_NATIVE_BUFFER_ANDROID, native_buffer, attrs); |
|
|
|
|
|
|
|
egl_texture_ = 0; |
|
|
|
glGenTextures(1, &egl_texture_); |
|
|
|
|
|
|
|
|
|
|
glGenFramebuffers(1, &fbo_); |
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_); |
|
|
|
|
|
|
|
|
|
|
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); |
|
|
|
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, egl_texture_, 0); |
|
|
|
|
|
|
FML_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); |
|
|
|
|
|
|
|
|
|
|
|
if(buffer != nullptr){ |
|
|
|
if (buffer != nullptr) |
|
|
|
{ |
|
|
|
if(image){ |
|
|
|
if (image) |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
eglDestroyImageKHR(egl_display_, image); |
|
|
|
|
|
|
|
glDeleteTextures(1, &egl_texture_); |
|
|
|
|
|
|
|
|
|
|
void UnitySurfaceManager::GetUnityContext() |
|
|
|
{ |
|
|
|
if(egl_unity_context_ != nullptr){ |
|
|
|
if (egl_unity_context_ != nullptr) |
|
|
|
{ |
|
|
|
FML_CHECK(egl_display_ != EGL_NO_DISPLAY) |
|
|
|
<< "Renderer type is invalid"; |
|
|
|
FML_CHECK(egl_display_ != EGL_NO_DISPLAY) |
|
|
|
<< "Renderer type is invalid"; |
|
|
|
auto *graphics = unity_interfaces->Get<IUnityGraphics>(); |
|
|
|
UnityGfxRenderer renderer = graphics->GetRenderer(); |
|
|
|
FML_DCHECK(renderer == kUnityGfxRendererOpenGLES30 || |
|
|
|
renderer == kUnityGfxRendererOpenGLES20 || |
|
|
|
renderer == kUnityGfxRendererVulkan); |
|
|
|
|
|
|
|
if (renderer == kUnityGfxRendererVulkan) |
|
|
|
{ |
|
|
|
m_UnityVulkan = unity_interfaces->Get<IUnityGraphicsVulkan>(); |
|
|
|
m_Instance = m_UnityVulkan->Instance(); |
|
|
|
LoadVulkanAPI(m_Instance.getInstanceProcAddr, m_Instance.instance); |
|
|
|
|
|
|
|
egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); // eglGetCurrentDisplay(); //
|
|
|
|
|
|
|
|
FML_CHECK(egl_display_ != EGL_NO_DISPLAY); |
|
|
|
|
|
|
|
eglBindAPI(EGL_OPENGL_ES_API); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Initialize the display connection.
|
|
|
|
FML_CHECK(eglInitialize(egl_display_, nullptr, nullptr) == EGL_TRUE) |
|
|
|