Skip to content

Commit 2abf37b

Browse files
SS-JIAfacebook-github-bot
authored andcommitted
Enable zero-size tensors (#3640)
Summary: As title. The approach is slightly different than in PyTorch Vulkan. Instead of binding no memory, we make a small allocation. The reason for this change is to account for the possibility that some zero size tensors are used as input but the output is not zero size. In that case we still need to be able to bind the zero size tensor to a shader. Differential Revision: D57450473
1 parent 7a35b6f commit 2abf37b

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

backends/vulkan/runtime/api/memory/Buffer.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,18 @@ VulkanBuffer::VulkanBuffer(
3838
memory_{},
3939
owns_memory_(allocate_memory),
4040
handle_(VK_NULL_HANDLE) {
41-
// Only allocate memory if the buffer has non-zero size
41+
// If the buffer size is 0, allocate a buffer with a size of 1 byte. This is
42+
// to ensure that there will be some resource that can be bound to a shader.
4243
if (size == 0) {
43-
return;
44+
buffer_properties_.size = 1u;
45+
buffer_properties_.mem_range = 1u;
4446
}
4547

4648
const VkBufferCreateInfo buffer_create_info{
4749
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
4850
nullptr, // pNext
4951
0u, // flags
50-
size, // size
52+
buffer_properties_.size, // size
5153
buffer_properties_.buffer_usage, // usage
5254
VK_SHARING_MODE_EXCLUSIVE, // sharingMode
5355
0u, // queueFamilyIndexCount

backends/vulkan/runtime/api/memory/Image.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,14 @@ VulkanImage::VulkanImage(
129129
VmaAllocatorInfo allocator_info{};
130130
vmaGetAllocatorInfo(allocator_, &allocator_info);
131131

132-
// If any dims are zero, then no memory will be allocated for the image.
132+
// If any dims are zero, then allocate a 1x1x1 image texture. This is to
133+
// ensure that there will be some resource that can be bound to a shader.
133134
if (image_props.image_extents.width == 0 ||
134135
image_props.image_extents.height == 0 ||
135136
image_props.image_extents.depth == 0) {
136-
return;
137+
image_properties_.image_extents.width = 1u;
138+
image_properties_.image_extents.height = 1u;
139+
image_properties_.image_extents.depth = 1u;
137140
}
138141

139142
const VkImageCreateInfo image_create_info{

backends/vulkan/test/vulkan_compute_api_test.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,38 @@ TEST_F(VulkanComputeAPITest, test_buffer_int8) {
259259
test_storage_buffer_type<int8_t, api::kQInt8>(16);
260260
}
261261

262+
TEST_F(VulkanComputeAPITest, test_zero_size_tensor) {
263+
// Simple test that performs a + b -> c
264+
265+
std::vector<int64_t> sizes = {0, 5, 7};
266+
vTensor a = CREATE_FLOAT_TEXTURE(sizes, /*allocate_memory = */ true);
267+
vTensor b = CREATE_FLOAT_TEXTURE(sizes, /*allocate_memory = */ true);
268+
vTensor c = CREATE_FLOAT_TEXTURE(sizes, /*allocate_memory = */ true);
269+
270+
// Fill input tensors
271+
fill_vtensor(a, 2.5f);
272+
fill_vtensor(b, 1.5f);
273+
274+
// a + b -> c
275+
record_binary_op(api::context(), "add", a, b, c);
276+
277+
// Extract output tensor
278+
std::vector<float> data_out = extract_vtensor(c);
279+
280+
// Assert all tensors are empty
281+
ASSERT_TRUE(a.numel() == 0);
282+
ASSERT_TRUE(b.numel() == 0);
283+
ASSERT_TRUE(c.numel() == 0);
284+
ASSERT_TRUE(a.nbytes() == 0);
285+
ASSERT_TRUE(b.nbytes() == 0);
286+
ASSERT_TRUE(c.nbytes() == 0);
287+
288+
// Check output
289+
for (size_t i = 0; i < data_out.size(); ++i) {
290+
CHECK_VALUE(data_out, i, 4.0f);
291+
}
292+
}
293+
262294
TEST_F(VulkanComputeAPITest, texture_add_sanity_check) {
263295
// Simple test that performs a + b -> c
264296

0 commit comments

Comments
 (0)