1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
/*
* Copyright (c) 2015-2024 The Khronos Group Inc.
* Copyright (C) 2025 Arm Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include <vector>
class PositiveTensor : public TensorTest {};
void TensorTest::InitBasicTensor() {
SetTargetApiVersion(VK_API_VERSION_1_4);
AddRequiredExtensions(VK_ARM_TENSORS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tensors);
RETURN_IF_SKIP(Init());
}
VkTensorDescriptionARM TensorTest::DefaultDesc() {
static std::vector<int64_t> dimensions{2ul};
static std::vector<int64_t> strides{1l};
static VkTensorDescriptionARM desc = vku::InitStructHelper();
desc.tiling = VK_TENSOR_TILING_LINEAR_ARM;
desc.format = VK_FORMAT_R8_SINT;
desc.dimensionCount = 1;
desc.pDimensions = dimensions.data();
desc.pStrides = strides.data();
desc.usage = VK_TENSOR_USAGE_SHADER_BIT_ARM;
return desc;
}
VkTensorCreateInfoARM TensorTest::DefaultCreateInfo(VkTensorDescriptionARM* desc) {
static VkTensorCreateInfoARM info = vku::InitStructHelper();
info.pDescription = desc;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
return info;
}
TEST_F(PositiveTensor, CreateTensor) {
TEST_DESCRIPTION("Create a tensor");
RETURN_IF_SKIP(InitBasicTensor());
auto desc = DefaultDesc();
auto info = DefaultCreateInfo(&desc);
vkt::Tensor tensor(*m_device, info);
}
TEST_F(PositiveTensor, ProtectedMemory) {
TEST_DESCRIPTION("Create a protected tensor");
AddRequiredFeature(vkt::Feature::protectedMemory);
RETURN_IF_SKIP(InitBasicTensor());
auto desc = DefaultDesc();
auto info = DefaultCreateInfo(&desc);
info.flags = VK_TENSOR_CREATE_PROTECTED_BIT_ARM;
vkt::Tensor tensor(*m_device, info);
tensor.BindToMem(VK_MEMORY_PROPERTY_PROTECTED_BIT);
}
TEST_F(PositiveTensor, DescriptorBuffer) {
TEST_DESCRIPTION("Create a tensor with replay capability");
AddRequiredFeature(vkt::Feature::descriptorBufferTensorDescriptors);
AddRequiredFeature(vkt::Feature::descriptorBufferCaptureReplay);
RETURN_IF_SKIP(InitBasicTensor());
auto desc = DefaultDesc();
auto info = DefaultCreateInfo(&desc);
info.flags = VK_TENSOR_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM;
vkt::Tensor tensor(*m_device, info);
tensor.BindToMem();
VkTensorViewCreateInfoARM tensor_view_create_info = vku::InitStructHelper();
tensor_view_create_info.tensor = tensor.handle();
tensor_view_create_info.format = tensor.Format();
tensor_view_create_info.flags = VK_TENSOR_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM;
vkt::TensorView view(*m_device, tensor_view_create_info);
VkTensorViewCaptureDescriptorDataInfoARM tensor_capture_desc_data_info = vku::InitStructHelper();
tensor_capture_desc_data_info.tensorView = view.handle();
uint32_t data = 0;
vk::GetTensorViewOpaqueCaptureDescriptorDataARM(*m_device, &tensor_capture_desc_data_info, &data);
}
TEST_F(PositiveTensor, DispatchShader) {
TEST_DESCRIPTION("Use a tensor in a shader");
AddRequiredFeature(vkt::Feature::shaderTensorAccess);
AddRequiredFeature(vkt::Feature::timelineSemaphore);
RETURN_IF_SKIP(InitBasicTensor());
vkt::Tensor tensor(*m_device);
tensor.BindToMem();
VkTensorViewCreateInfoARM tensor_view_create_info = vku::InitStructHelper();
tensor_view_create_info.tensor = tensor.handle();
tensor_view_create_info.format = tensor.Format();
vkt::TensorView view(*m_device, tensor_view_create_info);
vkt::Buffer buffer(*m_device, tensor.GetMemoryReqs().memoryRequirements.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
CreateComputePipelineHelper pipe(*m_device);
pipe.cs_ = VkShaderObj::CreateFromGLSL(this, tensor_shader_source, VK_SHADER_STAGE_COMPUTE_BIT);
std::vector<VkDescriptorSetLayoutBinding> bindings = {
{0, VK_DESCRIPTOR_TYPE_TENSOR_ARM, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr},
{1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}};
pipe.dsl_bindings_.resize(bindings.size());
memcpy(pipe.dsl_bindings_.data(), bindings.data(), bindings.size() * sizeof(VkDescriptorSetLayoutBinding));
pipe.CreateComputePipeline();
pipe.descriptor_set_.WriteDescriptorTensorInfo(0, &view.handle());
pipe.descriptor_set_.WriteDescriptorBufferInfo(1, buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
pipe.descriptor_set_.UpdateDescriptorSets();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe.pipeline_layout_, 0, 1,
&pipe.descriptor_set_.set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe);
vk::CmdDispatch(m_command_buffer.handle(), 1, 1, 1);
m_command_buffer.End();
m_default_queue->SubmitAndWait(m_command_buffer);
}
|