diff --git a/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.h b/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.h new file mode 100644 index 0000000..8994f3c --- /dev/null +++ b/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.h @@ -0,0 +1,32 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Scene/Texture.hpp" +#include "Vulkan/Scene/VulkanTexture.hpp" +#include + + +namespace OpenVulkano::Vulkan +{ + class MetalBackedTexture : public Scene::Texture + { + VulkanTexture m_vulkanTexture; + MTLTexture_id m_metalTexture = nullptr; + + public: + MetalBackedTexture() = default; + + ~MetalBackedTexture() { if (m_vulkanTexture) Close(); } + + void Init(ResourceManager* resManager, MTLTexture_id mtlTexture, bool ownsTexture); + + void Close(); + + operator bool() const { return m_vulkanTexture; } + }; +} diff --git a/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm b/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm new file mode 100644 index 0000000..91be222 --- /dev/null +++ b/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm @@ -0,0 +1,74 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "MetalBackedTexture.h" +#include +#import + +namespace OpenVulkano::Vulkan +{ + void MetalBackedTexture::Init(ResourceManager* resManager, MTLTexture_id mtlTexture, bool ownsTexture) + { + auto binding = Texture::DESCRIPTOR_SET_LAYOUT_BINDING; + + m_metalTexture = mtlTexture; + + resolution = { static_cast(mtlTexture.width), static_cast(mtlTexture.height), static_cast(mtlTexture.depth) }; + format = DataFormat::GetFromMetalPixelFormat(static_cast(mtlTexture.pixelFormat)); + + m_vulkanTexture.m_texture = this; + m_vulkanTexture.device = resManager->GetDevice(); + m_vulkanTexture.format = format; + m_vulkanTexture.extent = reinterpret_cast(resolution); + + VkImportMetalTextureInfoEXT importInfo; + importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT; + importInfo.pNext = nullptr; + importInfo.plane = VK_IMAGE_ASPECT_COLOR_BIT; + importInfo.mtlTexture = mtlTexture; + + vk::ImageCreateInfo imgCreateInfo { {}, vk::ImageType::e2D, m_vulkanTexture.format, m_vulkanTexture.extent, 1, 1 }; + + imgCreateInfo.sharingMode = vk::SharingMode::eExclusive; + imgCreateInfo.usage = vk::ImageUsageFlagBits::eSampled; + imgCreateInfo.tiling = vk::ImageTiling::eLinear; + imgCreateInfo.pNext = &importInfo; + + m_vulkanTexture.image = m_vulkanTexture.device.createImage(imgCreateInfo); + + vk::ImageViewCreateInfo imgViewCreateInfo { {}, m_vulkanTexture.image, vk::ImageViewType::e2D, imgCreateInfo.format }; + imgViewCreateInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; + imgViewCreateInfo.subresourceRange.baseMipLevel = 0; + imgViewCreateInfo.subresourceRange.levelCount = 1; + imgViewCreateInfo.subresourceRange.baseArrayLayer = 0; + imgViewCreateInfo.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + if (format == DataFormat::R8_UNORM) + { + imgViewCreateInfo.components.r = vk::ComponentSwizzle::eR; + imgViewCreateInfo.components.g = vk::ComponentSwizzle::eR; + imgViewCreateInfo.components.b = vk::ComponentSwizzle::eR; + imgViewCreateInfo.components.a = vk::ComponentSwizzle::eOne; + } + m_vulkanTexture.view = m_vulkanTexture.device.createImageView(imgViewCreateInfo); + + m_vulkanTexture.m_sampler = resManager->CreateSampler(VulkanTexture::DEFAULT_SAMPLER_CONFIG); + m_vulkanTexture.SetDescriptorSet(resManager, resManager->GetDescriptorLayoutSet(binding), binding); + + renderTexture = &m_vulkanTexture; + + if (!ownsTexture) m_metalTexture = nullptr; + } + + void MetalBackedTexture::Close() + { + m_vulkanTexture.Close(); + if (m_metalTexture) + { + [m_metalTexture release]; + m_metalTexture = nullptr; + } + } +}