blob: 222ff9742851e6ba4d276417404b4b148f039c66 [file] [log] [blame]
// Copyright 2019 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef IREE_HAL_CTS_COMMAND_BUFFER_COPY_BUFFER_TEST_H_
#define IREE_HAL_CTS_COMMAND_BUFFER_COPY_BUFFER_TEST_H_
#include <cstdint>
#include <vector>
#include "iree/base/api.h"
#include "iree/hal/api.h"
#include "iree/hal/cts/cts_test_base.h"
#include "iree/testing/gtest.h"
#include "iree/testing/status_matchers.h"
namespace iree::hal::cts {
using ::testing::ContainerEq;
namespace {
constexpr iree_device_size_t kDefaultAllocationSize = 1024;
} // namespace
class CommandBufferCopyBufferTest : public CTSTestBase<> {};
TEST_F(CommandBufferCopyBufferTest, CopyWholeBuffer) {
iree_hal_command_buffer_t* command_buffer = NULL;
IREE_ASSERT_OK(iree_hal_command_buffer_create(
device_, IREE_HAL_COMMAND_BUFFER_MODE_ONE_SHOT,
IREE_HAL_COMMAND_CATEGORY_TRANSFER, IREE_HAL_QUEUE_AFFINITY_ANY,
/*binding_capacity=*/0, &command_buffer));
uint8_t i8_val = 0x54;
std::vector<uint8_t> reference_buffer(kDefaultAllocationSize);
std::memset(reference_buffer.data(), i8_val, kDefaultAllocationSize);
// Create and fill a host buffer.
iree_hal_buffer_params_t host_params = {0};
host_params.type =
IREE_HAL_MEMORY_TYPE_HOST_LOCAL | IREE_HAL_MEMORY_TYPE_DEVICE_VISIBLE;
host_params.usage = IREE_HAL_BUFFER_USAGE_DISPATCH_STORAGE |
IREE_HAL_BUFFER_USAGE_TRANSFER |
IREE_HAL_BUFFER_USAGE_MAPPING;
iree_hal_buffer_t* host_buffer = nullptr;
IREE_ASSERT_OK(iree_hal_allocator_allocate_buffer(
device_allocator_, host_params, kDefaultAllocationSize, &host_buffer));
IREE_ASSERT_OK(iree_hal_device_transfer_h2d(
device_, reference_buffer.data(), host_buffer, 0, reference_buffer.size(),
IREE_HAL_TRANSFER_BUFFER_FLAG_DEFAULT, iree_infinite_timeout()));
// Create a device buffer.
iree_hal_buffer_params_t device_params = {0};
device_params.type =
IREE_HAL_MEMORY_TYPE_DEVICE_LOCAL | IREE_HAL_MEMORY_TYPE_HOST_VISIBLE;
device_params.usage = IREE_HAL_BUFFER_USAGE_DISPATCH_STORAGE |
IREE_HAL_BUFFER_USAGE_TRANSFER |
IREE_HAL_BUFFER_USAGE_MAPPING;
iree_hal_buffer_t* device_buffer = nullptr;
IREE_ASSERT_OK(iree_hal_allocator_allocate_buffer(
device_allocator_, device_params, kDefaultAllocationSize,
&device_buffer));
// Copy the host buffer to the device buffer.
IREE_ASSERT_OK(iree_hal_command_buffer_begin(command_buffer));
IREE_ASSERT_OK(iree_hal_command_buffer_copy_buffer(
command_buffer, /*source_ref=*/
iree_hal_make_buffer_ref(host_buffer, 0, kDefaultAllocationSize),
/*target_ref=*/
iree_hal_make_buffer_ref(device_buffer, 0, kDefaultAllocationSize),
IREE_HAL_COPY_FLAG_NONE));
IREE_ASSERT_OK(iree_hal_command_buffer_end(command_buffer));
IREE_ASSERT_OK(SubmitCommandBufferAndWait(command_buffer));
// Read the device buffer and compare.
std::vector<uint8_t> actual_data(kDefaultAllocationSize);
IREE_ASSERT_OK(iree_hal_device_transfer_d2h(
device_, device_buffer, /*source_offset=*/0,
/*target_buffer=*/actual_data.data(),
/*data_length=*/kDefaultAllocationSize,
IREE_HAL_TRANSFER_BUFFER_FLAG_DEFAULT, iree_infinite_timeout()));
EXPECT_THAT(actual_data, ContainerEq(reference_buffer));
// Must release the command buffer before resources used by it.
iree_hal_command_buffer_release(command_buffer);
iree_hal_buffer_release(device_buffer);
iree_hal_buffer_release(host_buffer);
}
TEST_F(CommandBufferCopyBufferTest, CopySubBuffer) {
iree_hal_command_buffer_t* command_buffer = NULL;
IREE_ASSERT_OK(iree_hal_command_buffer_create(
device_, IREE_HAL_COMMAND_BUFFER_MODE_ONE_SHOT,
IREE_HAL_COMMAND_CATEGORY_TRANSFER, IREE_HAL_QUEUE_AFFINITY_ANY,
/*binding_capacity=*/0, &command_buffer));
iree_hal_buffer_params_t device_params = {0};
device_params.type =
IREE_HAL_MEMORY_TYPE_DEVICE_LOCAL | IREE_HAL_MEMORY_TYPE_HOST_VISIBLE;
device_params.usage = IREE_HAL_BUFFER_USAGE_DISPATCH_STORAGE |
IREE_HAL_BUFFER_USAGE_TRANSFER |
IREE_HAL_BUFFER_USAGE_MAPPING;
iree_hal_buffer_t* device_buffer = NULL;
IREE_ASSERT_OK(iree_hal_allocator_allocate_buffer(
device_allocator_, device_params, kDefaultAllocationSize,
&device_buffer));
uint8_t i8_val = 0x88;
std::vector<uint8_t> reference_buffer(kDefaultAllocationSize);
std::memset(reference_buffer.data() + 8, i8_val,
kDefaultAllocationSize / 2 - 4);
// Create another host buffer with a smaller size.
iree_hal_buffer_params_t host_params = {0};
host_params.type =
IREE_HAL_MEMORY_TYPE_HOST_LOCAL | IREE_HAL_MEMORY_TYPE_DEVICE_VISIBLE;
host_params.usage = IREE_HAL_BUFFER_USAGE_DISPATCH_STORAGE |
IREE_HAL_BUFFER_USAGE_TRANSFER |
IREE_HAL_BUFFER_USAGE_MAPPING;
std::vector<uint8_t> host_buffer_data(kDefaultAllocationSize, i8_val);
iree_hal_buffer_t* host_buffer = NULL;
IREE_ASSERT_OK(iree_hal_allocator_allocate_buffer(
device_allocator_, host_params, host_buffer_data.size() / 2,
&host_buffer));
IREE_ASSERT_OK(iree_hal_device_transfer_h2d(
device_, host_buffer_data.data(), host_buffer, 0,
host_buffer_data.size() / 2, IREE_HAL_TRANSFER_BUFFER_FLAG_DEFAULT,
iree_infinite_timeout()));
// Copy the host buffer to the device buffer; zero fill the untouched bytes.
uint8_t zero_val = 0x0;
IREE_ASSERT_OK(iree_hal_command_buffer_begin(command_buffer));
IREE_ASSERT_OK(iree_hal_command_buffer_fill_buffer(
command_buffer,
iree_hal_make_buffer_ref(device_buffer, /*target_offset=*/0,
/*length=*/8),
&zero_val, /*pattern_length=*/sizeof(zero_val), IREE_HAL_FILL_FLAG_NONE));
IREE_ASSERT_OK(iree_hal_command_buffer_copy_buffer(
command_buffer,
iree_hal_make_buffer_ref(/*source_buffer=*/host_buffer,
/*source_offset=*/4,
/*length=*/kDefaultAllocationSize / 2 - 4),
iree_hal_make_buffer_ref(/*target_buffer=*/device_buffer,
/*target_offset=*/8,
/*length=*/kDefaultAllocationSize / 2 - 4),
IREE_HAL_COPY_FLAG_NONE));
IREE_ASSERT_OK(iree_hal_command_buffer_fill_buffer(
command_buffer,
iree_hal_make_buffer_ref(
device_buffer,
/*target_offset=*/8 + kDefaultAllocationSize / 2 - 4,
/*length=*/kDefaultAllocationSize -
(8 + kDefaultAllocationSize / 2 - 4)),
&zero_val,
/*pattern_length=*/sizeof(zero_val), IREE_HAL_FILL_FLAG_NONE));
IREE_ASSERT_OK(iree_hal_command_buffer_end(command_buffer));
IREE_ASSERT_OK(SubmitCommandBufferAndWait(command_buffer));
// Read the device buffer and compare.
std::vector<uint8_t> actual_data(kDefaultAllocationSize);
IREE_ASSERT_OK(iree_hal_device_transfer_d2h(
device_, device_buffer, /*source_offset=*/0,
/*target_buffer=*/actual_data.data(),
/*data_length=*/kDefaultAllocationSize,
IREE_HAL_TRANSFER_BUFFER_FLAG_DEFAULT, iree_infinite_timeout()));
EXPECT_THAT(actual_data, ContainerEq(reference_buffer));
// Must release the command buffer before resources used by it.
iree_hal_command_buffer_release(command_buffer);
iree_hal_buffer_release(device_buffer);
iree_hal_buffer_release(host_buffer);
}
TEST_F(CommandBufferCopyBufferTest, CopySubBufferIndirect) {
const int kHostBufferSlot = 0;
const int kDeviceBufferSlot = 1;
const int kBindingSlotCount = 2;
iree_hal_command_buffer_t* command_buffer = NULL;
IREE_ASSERT_OK(iree_hal_command_buffer_create(
device_, IREE_HAL_COMMAND_BUFFER_MODE_ONE_SHOT,
IREE_HAL_COMMAND_CATEGORY_TRANSFER, IREE_HAL_QUEUE_AFFINITY_ANY,
kBindingSlotCount, &command_buffer));
iree_hal_buffer_params_t device_params = {0};
device_params.type =
IREE_HAL_MEMORY_TYPE_DEVICE_LOCAL | IREE_HAL_MEMORY_TYPE_HOST_VISIBLE;
device_params.usage = IREE_HAL_BUFFER_USAGE_DISPATCH_STORAGE |
IREE_HAL_BUFFER_USAGE_TRANSFER |
IREE_HAL_BUFFER_USAGE_MAPPING;
iree_hal_buffer_t* device_buffer = NULL;
IREE_ASSERT_OK(iree_hal_allocator_allocate_buffer(
device_allocator_, device_params, kDefaultAllocationSize,
&device_buffer));
uint8_t i8_val = 0x88;
std::vector<uint8_t> reference_buffer(kDefaultAllocationSize);
std::memset(reference_buffer.data() + 8, i8_val,
kDefaultAllocationSize / 2 - 4);
// Create another host buffer with a smaller size.
iree_hal_buffer_params_t host_params = {0};
host_params.type =
IREE_HAL_MEMORY_TYPE_HOST_LOCAL | IREE_HAL_MEMORY_TYPE_DEVICE_VISIBLE;
host_params.usage = IREE_HAL_BUFFER_USAGE_DISPATCH_STORAGE |
IREE_HAL_BUFFER_USAGE_TRANSFER |
IREE_HAL_BUFFER_USAGE_MAPPING;
std::vector<uint8_t> host_buffer_data(kDefaultAllocationSize, i8_val);
iree_hal_buffer_t* host_buffer = NULL;
IREE_ASSERT_OK(iree_hal_allocator_allocate_buffer(
device_allocator_, host_params, host_buffer_data.size() / 2,
&host_buffer));
IREE_ASSERT_OK(iree_hal_device_transfer_h2d(
device_, host_buffer_data.data(), host_buffer, 0,
host_buffer_data.size() / 2, IREE_HAL_TRANSFER_BUFFER_FLAG_DEFAULT,
iree_infinite_timeout()));
// Copy the host buffer to the device buffer; zero fill the untouched bytes.
uint8_t zero_val = 0x0;
IREE_ASSERT_OK(iree_hal_command_buffer_begin(command_buffer));
IREE_ASSERT_OK(iree_hal_command_buffer_fill_buffer(
command_buffer,
iree_hal_make_indirect_buffer_ref(kDeviceBufferSlot, /*offset=*/0,
/*length=*/8),
&zero_val, /*pattern_length=*/sizeof(zero_val), IREE_HAL_FILL_FLAG_NONE));
IREE_ASSERT_OK(iree_hal_command_buffer_copy_buffer(
command_buffer,
iree_hal_make_indirect_buffer_ref(
kHostBufferSlot,
/*offset=*/4,
/*length=*/kDefaultAllocationSize / 2 - 4),
iree_hal_make_indirect_buffer_ref(
kDeviceBufferSlot,
/*offset=*/8,
/*length=*/kDefaultAllocationSize / 2 - 4),
IREE_HAL_COPY_FLAG_NONE));
IREE_ASSERT_OK(iree_hal_command_buffer_fill_buffer(
command_buffer,
iree_hal_make_indirect_buffer_ref(
kDeviceBufferSlot,
/*target_offset=*/8 + kDefaultAllocationSize / 2 - 4,
/*length=*/kDefaultAllocationSize -
(8 + kDefaultAllocationSize / 2 - 4)),
&zero_val,
/*pattern_length=*/sizeof(zero_val), IREE_HAL_FILL_FLAG_NONE));
IREE_ASSERT_OK(iree_hal_command_buffer_end(command_buffer));
const iree_hal_buffer_binding_t bindings[] = {
/*kHostBufferSlot=*/{host_buffer, 0, IREE_HAL_WHOLE_BUFFER},
/*kDeviceBufferSlot=*/{device_buffer, 0, IREE_HAL_WHOLE_BUFFER},
};
IREE_ASSERT_OK(SubmitCommandBufferAndWait(command_buffer,
iree_hal_buffer_binding_table_t{
IREE_ARRAYSIZE(bindings),
bindings,
}));
// Read the device buffer and compare.
std::vector<uint8_t> actual_data(kDefaultAllocationSize);
IREE_ASSERT_OK(iree_hal_device_transfer_d2h(
device_, device_buffer, /*source_offset=*/0,
/*target_buffer=*/actual_data.data(),
/*data_length=*/kDefaultAllocationSize,
IREE_HAL_TRANSFER_BUFFER_FLAG_DEFAULT, iree_infinite_timeout()));
EXPECT_THAT(actual_data, ContainerEq(reference_buffer));
// Must release the command buffer before resources used by it.
iree_hal_command_buffer_release(command_buffer);
iree_hal_buffer_release(device_buffer);
iree_hal_buffer_release(host_buffer);
}
} // namespace iree::hal::cts
#endif // IREE_HAL_CTS_COMMAND_BUFFER_COPY_BUFFER_TEST_H_