浏览代码

vkimage & fbo

/siyaoH-1.17-vulkan2
siyao 3 年前
当前提交
17a5ebbc
共有 1 个文件被更改,包括 209 次插入216 次删除
  1. 425
      engine/src/shell/platform/unity/android/unity_surface_manager.cc

425
engine/src/shell/platform/unity/android/unity_surface_manager.cc


#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); \
#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

{
return;
}
// EGLint major, minor;
// egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
// eglInitialize(egl_display_, &major, &minor);
// egl_unity_context_ = eglGetCurrentContext();
// FML_CHECK(egl_display_ != EGL_NO_DISPLAY)
// << "Renderer type is invalid";
egl_display_ = eglGetCurrentDisplay();
egl_unity_context_ = eglGetCurrentContext();
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;
}
bool UnitySurfaceManager::Initialize(IUnityInterfaces *unity_interfaces)
{
auto *graphics = unity_interfaces->Get<IUnityGraphics>();

m_UnityVulkan = unity_interfaces->Get<IUnityGraphicsVulkan>();
m_Instance = m_UnityVulkan->Instance();
LoadVulkanAPI(m_Instance.getInstanceProcAddr, m_Instance.instance);
// auto VkPhysicalDevice = m_Instance.physicalDevice;
// VkPhysicalDeviceMemoryProperties mempryProperties;
// vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice, &mempryProperties);
auto vkDevice = m_Instance.device;
// auto memoryPropertys = m_Instance.memoryTypeIndex;
VkImage vkImage;
bool useExternalFormat = true;
// // AHarewareBuffer android api >= 26
// AHardwareBuffer* buffer = nullptr;
AHardwareBuffer *buffer = nullptr;
AHardwareBuffer_Desc usage = {};
// filling in the usage for HardwareBuffer
usage.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
usage.height = 10000; //format.height;
usage.width = 10000; //format.width;
usage.layers = 1;
usage.rfu0 = 0;
usage.rfu1 = 0;
usage.stride = 0;
usage.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
auto error = AHardwareBuffer_allocate(&usage, &buffer);
VkResult err;
// AHardwareBuffer_Desc hwbDesc;
// hwbDesc.width = DEV_W;
// hwbDesc.height = DEV_H;
// hwbDesc.layers = 1;
// GrVkImageInfo info(
// image.image, GrVkAlloc(image.memory.memory, image.memory.offset, image.memory.size, image.memory.flags),
// image.tiling,
// image.layout,
// image.format,
// image.mipCount);
// hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
// AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
// AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
// AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
// hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
// // The following three are not used in the allocate
// hwbDesc.stride = 0;
// hwbDesc.rfu0= 0;
// hwbDesc.rfu1= 0;
// AHardwareBuffer_Desc bufferDesc;
// AHardwareBuffer_describe(buffer, &bufferDesc);
// if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
// ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
// AHardwareBuffer_release(buffer);
// return;
// }
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);
bool check = false;
check = VK_FORMAT_R8G8B8A8_UNORM == formatInfo.format;
check = VK_FORMAT_UNDEFINED == formatInfo.format;
auto device = m_Instance.device;
auto physicalDevice = m_Instance.physicalDevice;
VkImage image = 0;
VkImageCreateInfo imageInfo{};
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 = useExternalFormat ? &externalFormat : nullptr,
.handleTypes =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
};
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (true)
{ //forWrite) {
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
VkImageCreateInfo imageInfo = {};
imageInfo.pNext = &externalCreateInfo;
imageInfo.flags = 0;
imageInfo.extent.width = 100;
imageInfo.extent.height = 100;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.format = VK_FORMAT_B8G8R8A8_UNORM;
imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
imageInfo.format =
formatInfo.format;
imageInfo.extent = {
100, //bufferDesc.width,
100, //bufferDesc.height,
1,
};
imageInfo.mipLevels = 1, imageInfo.arrayLayers = 1;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.usage = usageFlags;
vkCreateImage(device, &imageInfo, nullptr, &image);
// ... // create the image as normal
VkMemoryRequirements memReqs; // = device->getImageMemoryRequirements(image);
vkGetImageMemoryRequirements(device, image, &memReqs);
VkMemoryAllocateInfo memAllocInfo;
const auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
VkExportMemoryAllocateInfoKHR exportAllocInfo{
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, nullptr, handle_type};
memAllocInfo.pNext = &exportAllocInfo;
memAllocInfo.allocationSize = memReqs.size;
imageInfo.queueFamilyIndexCount = 0;
imageInfo.pQueueFamilyIndices = 0;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
auto result = vkCreateImage(vkDevice, &imageInfo, nullptr, &vkImage);
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 = vkImage,
.buffer = VK_NULL_HANDLE,
};
// android的hardbuffer位置(properties)
VkMemoryRequirements requires;
vkGetImageMemoryRequirements(vkDevice, vkImage, &requires);
VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
phyDevMemProps.pNext = nullptr;
uint32_t memoryTypeIndex = 0;
uint32_t typeIndex = 0;
uint32_t heapIndex = 0;
VkPhysicalDeviceMemoryProperties phyDevMemProps;
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &phyDevMemProps);
for (uint32_t i = 0; i < phyDevMemProps.memoryTypeCount && !foundHeap; ++i)
vkGetPhysicalDeviceMemoryProperties2(m_Instance.physicalDevice, &phyDevMemProps);
uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i)
if (VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT & (1 << i))
if (properties.memoryTypeBits & (1 << i))
// Map host-visible memory.
if (phyDevMemProps.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
const VkPhysicalDeviceMemoryProperties &pdmp = phyDevMemProps.memoryProperties;
uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
memoryTypeIndex = i;
typeIndex = i;
heapIndex = pdmp.memoryTypes[i].heapIndex;
memAllocInfo.memoryTypeIndex = memoryTypeIndex;
// physicalDevice->set_memory_type(
// memReqs.memoryTypeBits, &memAllocInfo, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkDeviceMemory memory;
vkAllocateMemory(device, &memAllocInfo, NULL, &memory);
// memory = device->allocateMemory(memAllocInfo);
vkBindImageMemory(device, image, memory, 0);
uint32_t memoryTypeIndex = 0;
// VkPhysicalDeviceMemoryProperties memoryPropertys; //???
AHardwareBuffer *buffer;
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;
VkMemoryGetAndroidHardwareBufferInfoANDROID meminfo;
meminfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
meminfo.pNext = nullptr;
meminfo.memory = memory;
vkGetMemoryAndroidHardwareBufferANDROID(device, &meminfo, &buffer); // android api level 28
// HANDLE sharedMemoryHandle = device->getMemoryWin32HandleKHR({
// texture.memory, VkExternalMemoryHandleTypeFlags::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
// });
// EGLDisplay display = eglGetCurrentDisplay();
VkDeviceMemory memory; //???
vkAllocateMemory(vkDevice, &memoryInfo, nullptr, &memory);
VkBindImageMemoryInfo bindImageInfo;
bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
bindImageInfo.pNext = nullptr;
bindImageInfo.image = vkImage;
bindImageInfo.memory = memory;
bindImageInfo.memoryOffset = 0;
// vkBindImageMemory2KHR(vkDevice, 1, &bindImageInfo);
vkBindImageMemory2(vkDevice, 1, &bindImageInfo);
bool success = false;
EGLint major, minor;
// android绑定AHardwareBuffer与egl image
EGLClientBuffer native_buffer = eglGetNativeClientBufferANDROID(buffer);
assert(native_buffer);
auto success = false;
egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
auto error = eglGetError();
eglInitialize(egl_display_, &major, &minor);
error = eglGetError();
egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); // eglGetCurrentDisplay(); //
auto xx2 = egl_display_ == EGL_NO_DISPLAY;
auto xxxx = eglInitialize(egl_display_, nullptr, nullptr) == EGL_TRUE;
eglBindAPI(EGL_OPENGL_ES_API);
error = eglGetError();
FML_CHECK(success) << "Could not choose an EGL configuration.";
eglBindAPI(EGL_OPENGL_ES_API);
error = eglGetError();
error = eglGetError();
std::tie(success, egl_resource_context_) = CreateContext(egl_display_, egl_config_, egl_context_);
eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_context_);
error = eglGetError();

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
error = eglGetError();
EGLint ver0 = -1;
EGLint ver1 = -1;
EGLint ver2 = -1;
EGLint ver3 = -1;
eglQueryContext(egl_display_, egl_context_, EGL_CONTEXT_CLIENT_VERSION, &ver0);
eglQueryContext(egl_display_, egl_context_, EGL_CONFIG_ID, &ver1);
eglQueryContext(egl_display_, egl_context_, EGL_CONTEXT_CLIENT_TYPE, &ver2);
eglQueryContext(egl_display_, egl_context_, EGL_RENDER_BUFFER, &ver3);
AHardwareBuffer_Desc usage;
EGLint attrs[] = {EGL_NONE};
EGLImageKHR image = eglCreateImageKHR(egl_display_, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, native_buffer, attrs);
// assert(image != EGL_NO_IMAGE_KHR);
if (image == EGL_NO_IMAGE_KHR)
{
int32_t errorId = eglGetError();
// logMessage(LogLevel::error, "not create image,error id" + errorId);
}
// filling in the usage for HardwareBuffer
usage.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
usage.height = 100; //outputHeight;
usage.width = 100; // outputWidth;
usage.layers = 1;
usage.rfu0 = 0;
usage.rfu1 = 0;
usage.stride = 10;
usage.usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
AHardwareBuffer *graphicBuf;
AHardwareBuffer_allocate(&usage, &graphicBuf); // it's worth to check the return code
// ACTUAL parameters of the AHardwareBuffer which it reports
AHardwareBuffer_Desc usage1;
// for stride, see below
AHardwareBuffer_describe(graphicBuf, &usage1);
// get the native buffer
EGLClientBuffer clientBuf = eglGetNativeClientBufferANDROID(graphicBuf);
error = eglGetError();
// obtaining the EGL display
// specifying the image attributes
// EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
EGLint eglImageAttributes[] = { EGL_NONE};
// creating an EGL image
// EGLImageKHR imageEGL = eglCreateImageKHR(egl_display_, egl_context_, EGL_NATIVE_BUFFER_ANDROID, clientBuf, eglImageAttributes);
EGLImageKHR imageEGL = eglCreateImageKHR(egl_display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuf, eglImageAttributes);
error = eglGetError();
/**
* @note this part should be earlies than any draw or framebuffer options.
* @note refer to answer of @solidpixel at https://stackoverflow.com/questions/64447069/use-gleglimagetargettexture2does-to-replace-glreadpixels-on-android
* @{
*/
// binding the OUTPUT texture
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, imageEGL);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
glBindTexture(bindType, 0);
// glBindTexture(bindType, 0);
auto x = glCheckFramebufferStatus(GL_FRAMEBUFFER);
// glewInit();
error = eglGetError();
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(buffer);
error = eglGetError();
bool isProtectedContent = true;
EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
error = eglGetError();
auto xegl = eglGetCurrentContext();
// EGLImageKHR imagekhr = eglCreateImageKHR(egl_display_, egl_context_, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attribs);
EGLImageKHR imagekhr = eglCreateImageKHR(egl_display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attribs);
error = eglGetError();
GLint old_framebuffer_binding;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_framebuffer_binding);
error = eglGetError();
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, imagekhr);
error = eglGetError();
FML_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, old_framebuffer_binding);
//-------------------
UnityVulkanPluginEventConfig config_1;
config_1.graphicsQueueAccess = kUnityVulkanGraphicsQueueAccess_DontCare;
config_1.renderPassPrecondition = kUnityVulkanRenderPass_EnsureInside;
config_1.flags =
kUnityVulkanEventConfigFlag_EnsurePreviousFrameSubmission |
kUnityVulkanEventConfigFlag_ModifiesCommandBuffersState;
m_UnityVulkan->ConfigureEvent(1, &config_1);
GrVkBackendContext vk_backend_context;
vk_backend_context.fInstance = m_Instance.instance;
vk_backend_context.fPhysicalDevice = m_Instance.physicalDevice;
vk_backend_context.fDevice = m_Instance.device;
vk_backend_context.fQueue = m_Instance.graphicsQueue;
vk_backend_context.fGraphicsQueueIndex = m_Instance.queueFamilyIndex;
vk_backend_context.fGetProc =
[getInstanceProc = m_Instance.getInstanceProcAddr,
getDeviceProc = my_vkGetDeviceProcAddr](
const char *proc_name, VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE)
{
return getDeviceProc(device, proc_name);
}
return getInstanceProc(instance, proc_name);
};
gr_context_ = GrContext::MakeVulkan(vk_backend_context);
auto valid_ = true;
GLenum x = glCheckFramebufferStatus(GL_FRAMEBUFFER);
auto xb = x == GL_FRAMEBUFFER_COMPLETE;
return success;
}

正在加载...
取消
保存