Skip to content

Commit

Permalink
Add ability to create exportable textures
Browse files Browse the repository at this point in the history
Reviewed By: ChristianK275, corporateshark

Differential Revision: D66836047

fbshipit-source-id: 359a4ab3c0c9907dd2dc8abc1718883ba99a3725
  • Loading branch information
Jason Zink authored and facebook-github-bot committed Feb 6, 2025
1 parent 4790423 commit 1ca69a8
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 15 deletions.
9 changes: 9 additions & 0 deletions src/igl/Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,8 @@ struct TextureDesc {
*/
enum class TextureTiling : uint8_t { Optimal, Linear };

enum class TextureExportability : uint8_t { NoExport, Exportable };

uint32_t width = 1;
uint32_t height = 1;
uint32_t depth = 1;
Expand All @@ -489,6 +491,7 @@ struct TextureDesc {
TextureFormat format = TextureFormat::Invalid;
ResourceStorage storage = ResourceStorage::Invalid;
TextureTiling tiling = TextureTiling::Optimal;
TextureExportability exportability = TextureExportability::NoExport;

std::string debugName;

Expand Down Expand Up @@ -521,6 +524,7 @@ struct TextureDesc {
format,
ResourceStorage::Invalid,
TextureTiling::Optimal,
TextureExportability::NoExport,
debugName ? debugName : ""};
}

Expand Down Expand Up @@ -553,6 +557,7 @@ struct TextureDesc {
format,
ResourceStorage::Invalid,
TextureTiling::Optimal,
TextureExportability::NoExport,
debugName ? debugName : "",
};
}
Expand Down Expand Up @@ -583,6 +588,7 @@ struct TextureDesc {
format,
ResourceStorage::Invalid,
TextureTiling::Optimal,
TextureExportability::NoExport,
debugName ? debugName : ""};
}

Expand Down Expand Up @@ -614,6 +620,7 @@ struct TextureDesc {
format,
ResourceStorage::Invalid,
TextureTiling::Optimal,
TextureExportability::NoExport,
debugName ? debugName : ""};
}

Expand Down Expand Up @@ -642,6 +649,7 @@ struct TextureDesc {
format,
ResourceStorage::Invalid,
TextureTiling::Optimal,
TextureExportability::NoExport,
debugName ? debugName : ""};
}

Expand Down Expand Up @@ -672,6 +680,7 @@ struct TextureDesc {
format,
ResourceStorage::Shared,
TextureTiling::Optimal,
TextureExportability::NoExport,
debugName ? debugName : ""};
}
#endif // defined(IGL_ANDROID_HWBUFFER_SUPPORTED)
Expand Down
6 changes: 6 additions & 0 deletions src/igl/metal/Device.mm
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@
"Array textures are only supported when type is TwoDArray.");
return nullptr;
}
if (desc.exportability != TextureDesc::TextureExportability::NoExport) {
Result::setResult(outResult,
Result::Code::Unimplemented,
"Exportable textures are not supported on this platform.");
return nullptr;
};

MTLTextureDescriptor* metalDesc = [MTLTextureDescriptor new];
metalDesc.textureType = Texture::convertType(sanitized.type, sanitized.numSamples);
Expand Down
4 changes: 4 additions & 0 deletions src/igl/opengl/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ Result Texture::create(const TextureDesc& desc, bool hasStorageAlready) {
return Result{Result::Code::Unsupported,
"Array textures are only supported when type is TwoDArray."};
}
if (desc.exportability != TextureDesc::TextureExportability::NoExport) {
return Result{Result::Code::Unimplemented,
"Exportable textures are not supported on this platform."};
}
if (IGL_DEBUG_VERIFY(!isCreated_)) {
isCreated_ = true;
IGL_DEBUG_ASSERT(desc.format != TextureFormat::Invalid && desc.format == getFormat());
Expand Down
50 changes: 50 additions & 0 deletions src/igl/tests/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include "Texture.h"
#include <igl/Common.h>

namespace igl::tests {

Expand Down Expand Up @@ -738,4 +739,53 @@ TEST_F(TextureTest, ValidateRange3D) {
EXPECT_FALSE(ret.isOk());
}

//
// Texture Export Support Test
//
// This test verifies:
// 1. NoExport textures can be created and used on all platforms
// 2. Exportable textures work only on supported platforms
// 3. Basic texture operations work for both types where supported
//
TEST_F(TextureTest, ExportableTexture) {
Result ret;

// Test NoExport texture (should work on all platforms)
auto texDesc =
TextureDesc::new2D(TextureFormat::RGBA_UNorm8, 8, 8, TextureDesc::TextureUsageBits::Sampled);
texDesc.exportability = TextureDesc::TextureExportability::NoExport;

auto texNoExport = iglDev_->createTexture(texDesc, &ret);
EXPECT_TRUE(ret.isOk());
ASSERT_TRUE(texNoExport != nullptr);

// Verify basic texture operations
auto rangeDesc = TextureRangeDesc::new2D(0, 0, 8, 8);
std::vector<uint32_t> inputData(64, 0x80808080);
texNoExport->upload(rangeDesc, inputData.data());
util::validateUploadedTexture(*iglDev_, *cmdQueue_, texNoExport, inputData.data(), "NoExport");

// Test Exportable texture (platform dependent)
texDesc.exportability = TextureDesc::TextureExportability::Exportable;
auto texExportable = iglDev_->createTexture(texDesc, &ret);

#if IGL_PLATFORM_WIN32 || IGL_PLATFORM_LINUX || IGL_PLATFORM_ANDROID
if (iglDev_->getBackendType() == BackendType::Vulkan) {
EXPECT_TRUE(ret.isOk());
ASSERT_TRUE(texExportable != nullptr);

// Verify basic texture operations
texExportable->upload(rangeDesc, inputData.data());
util::validateUploadedTexture(
*iglDev_, *cmdQueue_, texExportable, inputData.data(), "Exportable");
} else {
EXPECT_EQ(ret.code, Result::Code::Unimplemented);
ASSERT_TRUE(texExportable == nullptr);
}
#else
EXPECT_EQ(ret.code, Result::Code::Unimplemented);
ASSERT_TRUE(texExportable == nullptr);
#endif
}

} // namespace igl::tests
59 changes: 44 additions & 15 deletions src/igl/vulkan/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,22 +164,51 @@ Result Texture::create(const TextureDesc& desc) {
}

Result result;
auto image = ctx.createImage(
imageType,
VkExtent3D{(uint32_t)desc_.width, (uint32_t)desc_.height, (uint32_t)desc_.depth},
vkFormat,
(uint32_t)desc_.numMipLevels,
arrayLayerCount,
tiling,
usageFlags,
memFlags,
createFlags,
samples,
&result,
debugNameImage.c_str());
if (!IGL_DEBUG_VERIFY(result.isOk())) {
return result;
VulkanImage image;

if (desc_.exportability == TextureDesc::TextureExportability::NoExport) {
image = ctx.createImage(
imageType,
VkExtent3D{(uint32_t)desc_.width, (uint32_t)desc_.height, (uint32_t)desc_.depth},
vkFormat,
(uint32_t)desc_.numMipLevels,
arrayLayerCount,
tiling,
usageFlags,
memFlags,
createFlags,
samples,
&result,
debugNameImage.c_str());
if (!IGL_DEBUG_VERIFY(result.isOk())) {
return result;
}
} else if (desc_.exportability == TextureDesc::TextureExportability::Exportable) {
#if IGL_PLATFORM_WINDOWS || IGL_PLATFORM_LINUX || IGL_PLATFORM_ANDROID

image = igl::vulkan::VulkanImage::createWithExportMemory(
ctx,
ctx.getVkDevice(),
VkExtent3D{.width = (uint32_t)desc_.width,
.height = (uint32_t)desc_.height,
.depth = (uint32_t)desc_.depth},
imageType,
vkFormat,
(uint32_t)desc_.numMipLevels,
arrayLayerCount,
tiling,
usageFlags,
createFlags,
samples,
"vulkan export memory image");

#else // IGL_PLATFORM_WINDOWS || IGL_PLATFORM_LINUX || IGL_PLATFORM_ANDROID
// Currently only Mac is not supported.
return Result(Result::Code::Unimplemented,
"Exportable textures are not supported on this platform.");
#endif // IGL_PLATFORM_WINDOWS || IGL_PLATFORM_LINUX || IGL_PLATFORM_ANDROID
}

if (!IGL_DEBUG_VERIFY(image.valid())) {
return Result(Result::Code::InvalidOperation, "Cannot create VulkanImage");
}
Expand Down

0 comments on commit 1ca69a8

Please sign in to comment.