Skip to content

Commit e764959

Browse files
jorgep31415facebook-github-bot
authored andcommitted
Enable vTensor creation from external image (#5993)
Summary: Pull Request resolved: #5993 Nearly all metadata is initialized to null/dummy values, except those absolutely needed in the pipeline: (1) image extents, (2) logical limits. ghstack-source-id: 247078909 exported-using-ghexport Reviewed By: SS-JIA Differential Revision: D63843819 fbshipit-source-id: 71a52800fc5b79953ab98a8b549b12b4760db757
1 parent 991f0a9 commit e764959

File tree

7 files changed

+133
-0
lines changed

7 files changed

+133
-0
lines changed

backends/vulkan/runtime/api/containers/Tensor.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313
namespace vkcompute {
1414
namespace api {
1515

16+
std::vector<int64_t> calculate_sizes(
17+
const vkapi::VulkanImage& image,
18+
const utils::GPUMemoryLayout memory_layout) {
19+
auto sizes = std::vector<int64_t>{
20+
image.extents().width, image.extents().height, image.extents().depth};
21+
const auto packed_dim = utils::to_packed_dim<int32_t>(memory_layout);
22+
sizes.at(packed_dim) *= 4;
23+
return sizes;
24+
}
25+
1626
std::vector<int64_t> calculate_dim_order(
1727
const size_t ndim,
1828
const int32_t packed_dim) {
@@ -186,6 +196,18 @@ utils::uvec3 calculate_image_extents(
186196
// vTensorStorage
187197
//
188198

199+
utils::StorageType storage_type(const vkapi::VulkanImage& image) {
200+
const auto type = image.type();
201+
switch (type) {
202+
case VK_IMAGE_TYPE_3D:
203+
return utils::kTexture3D;
204+
case VK_IMAGE_TYPE_2D:
205+
return utils::kTexture2D;
206+
default:
207+
VK_THROW("Unsupported image type", type);
208+
}
209+
}
210+
189211
vkapi::VulkanImage allocate_image(
190212
Context* const context_ptr,
191213
utils::uvec3& image_extents,
@@ -281,6 +303,21 @@ vTensorStorage::vTensorStorage(
281303
last_access_{},
282304
has_copies_{false} {}
283305

306+
vTensorStorage::vTensorStorage(
307+
Context* const context,
308+
const vkapi::VulkanImage& image)
309+
: context_(context),
310+
storage_type_{storage_type(image)},
311+
image_extents_(
312+
{image.extents().width,
313+
image.extents().height,
314+
image.extents().depth}),
315+
buffer_length_{0},
316+
buffer_offset_{0},
317+
image_(image),
318+
buffer_(vkapi::VulkanBuffer()),
319+
last_access_{} {}
320+
284321
vTensorStorage::vTensorStorage(
285322
vTensorStorage& other,
286323
const int64_t buffer_offset)
@@ -446,6 +483,33 @@ vTensor::vTensor(
446483
}
447484

448485
// NOLINTNEXTLINE
486+
vTensor::vTensor(
487+
Context* context,
488+
const vkapi::VulkanImage& image,
489+
const utils::GPUMemoryLayout memory_layout)
490+
: dtype_(vkapi::element_scalartype(image.format())),
491+
// Calculate tensor metadata
492+
sizes_(calculate_sizes(image, memory_layout)),
493+
packed_dim_(utils::to_packed_dim<int32_t>(memory_layout)),
494+
dim_order_(),
495+
axis_map_(default_axis_map()),
496+
strides_(),
497+
numel_(utils::multiply_integers(sizes_)),
498+
padded_sizes_(calculate_padded_sizes(sizes_, packed_dim_)),
499+
unsqueezed_strides_(),
500+
padded_numel_(utils::multiply_integers(padded_sizes_)),
501+
logical_limits_(),
502+
// Utility Uniform Buffers that can be passed to shaders as arguments
503+
sizes_uniform_(),
504+
strides_uniform_(),
505+
numel_uniform_(),
506+
axis_map_uniform_(),
507+
logical_limits_uniform_(),
508+
// Construct Tensor storage
509+
storage_(context, image) {
510+
set_logical_limits(storage_.image_extents_);
511+
}
512+
449513
vTensor::vTensor(vTensor& other)
450514
: dtype_(other.dtype_),
451515
// Copy tensor size metadata

backends/vulkan/runtime/api/containers/Tensor.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ class vTensorStorage final {
9595
const vkapi::ScalarType dtype,
9696
const bool allocate_memory = true);
9797

98+
vTensorStorage(Context* const context, const vkapi::VulkanImage& image);
99+
98100
protected:
99101
/*
100102
* This allows for creation of tensors that use the same underlying storage
@@ -185,6 +187,11 @@ class vTensor final {
185187

186188
vTensor(const vTensor& other) = delete;
187189

190+
explicit vTensor(
191+
Context* context,
192+
const vkapi::VulkanImage& image,
193+
const utils::GPUMemoryLayout memory_layout = utils::kChannelsPacked);
194+
188195
/*
189196
* This constructor allows for the creation of a vTensor that references the
190197
* same buffer resource of another vTensor, with the same sizes and strides

backends/vulkan/runtime/graph/ComputeGraph.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,13 @@ ValueRef ComputeGraph::add_tensor(
296296
sizes, dtype, suggested_memory_layout(sizes), shared_object_idx);
297297
}
298298

299+
ValueRef ComputeGraph::add_tensor(const vkapi::VulkanImage& image) {
300+
ValueRef idx(static_cast<int>(values_.size()));
301+
check_no_active_value_ptrs();
302+
values_.emplace_back(api::vTensor(context(), image));
303+
return idx;
304+
}
305+
299306
ValueRef ComputeGraph::add_tensor_view(const ValueRef vref) {
300307
const vTensorPtr t = get_tensor(vref);
301308
ValueRef idx(static_cast<int>(values_.size()));

backends/vulkan/runtime/graph/ComputeGraph.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,11 @@ class ComputeGraph final {
466466
const vkapi::ScalarType dtype,
467467
const int64_t shared_object_idx = -1);
468468

469+
/*
470+
* Add a `api::vTensor` value to the graph with the specified image.
471+
*/
472+
ValueRef add_tensor(const vkapi::VulkanImage& image);
473+
469474
/*
470475
* Add a `api::vTensor` value to the graph with the properties of `vref`.
471476
*/

backends/vulkan/runtime/vk_api/Types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ inline ScalarType element_scalartype(const VkFormat vkformat) {
8484
case VK_FORMAT_R8G8B8A8_SINT:
8585
return kChar;
8686
case VK_FORMAT_R8G8B8A8_UINT:
87+
case VK_FORMAT_R8G8B8A8_UNORM:
8788
return kByte;
8889
case VK_FORMAT_R32G32B32A32_SINT:
8990
return kInt;

backends/vulkan/runtime/vk_api/memory/Image.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ class VulkanImage final {
180180
return memory_.allocation;
181181
}
182182

183+
inline VkImageType type() const {
184+
return image_properties_.image_type;
185+
}
186+
183187
inline VkFormat format() const {
184188
return image_properties_.image_format;
185189
}

backends/vulkan/test/vulkan_compute_api_test.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
#include <executorch/backends/vulkan/runtime/graph/ops/impl/utils/QPackUtils.h>
2525

26+
#include <executorch/backends/vulkan/runtime/vk_api/VkUtils.h>
27+
2628
#include <executorch/backends/vulkan/test/utils/test_utils.h>
2729

2830
using namespace vkcompute;
@@ -1094,6 +1096,49 @@ TEST_F(VulkanComputeAPITest, print_object_sizes) {
10941096
EXPECT_TRUE(sizeof(ExecuteNode) < 500);
10951097
}
10961098

1099+
TEST_F(VulkanComputeAPITest, test_tensor_creation_from_vulkan_image) {
1100+
const auto w = 16;
1101+
const auto h = 12;
1102+
const auto d = 1;
1103+
const utils::uvec3 image_extents = {w, h, d};
1104+
1105+
vkapi::Adapter* adapter_ptr = context()->adapter_ptr();
1106+
1107+
vkapi::ImageSampler::Properties sampler_props{
1108+
VK_FILTER_NEAREST,
1109+
VK_SAMPLER_MIPMAP_MODE_NEAREST,
1110+
VK_SAMPLER_ADDRESS_MODE_REPEAT,
1111+
VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1112+
};
1113+
1114+
VkFormat image_format = VK_FORMAT_R32G32B32A32_SFLOAT;
1115+
VkImageType image_type = VK_IMAGE_TYPE_3D;
1116+
VkImageViewType image_view_type = VK_IMAGE_VIEW_TYPE_3D;
1117+
1118+
VkSampler sampler = adapter_ptr->sampler_cache().retrieve(sampler_props);
1119+
1120+
auto image = adapter_ptr->vma().create_image(
1121+
context()->device(),
1122+
vkapi::create_extent3d(image_extents),
1123+
image_format,
1124+
image_type,
1125+
image_view_type,
1126+
sampler_props,
1127+
sampler,
1128+
/*allow_transfer = */ true,
1129+
/*allocate_memory = */ true);
1130+
1131+
auto tensor = vTensor(context(), image);
1132+
1133+
const auto exp_sizes = std::vector<int64_t>{w, h, d * 4};
1134+
EXPECT_TRUE(tensor.sizes() == exp_sizes);
1135+
EXPECT_TRUE(tensor.packed_dim() == 2);
1136+
1137+
const auto exp_numel = w * h * d * 4;
1138+
EXPECT_TRUE(tensor.numel() == exp_numel);
1139+
EXPECT_TRUE(tensor.padded_numel() == exp_numel);
1140+
}
1141+
10971142
TEST(VulkanComputeGraphTest, test_values_scalars) {
10981143
GraphConfig config;
10991144
ComputeGraph graph(config);

0 commit comments

Comments
 (0)