blob: 5292b7573922f9c8965667abbe494f4235609818 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <gtest/gtest.h>
#include "hwcpipe.h"
#include "src/graphics/tests/common/vulkan_context.h"
#include <vulkan/vulkan.hpp>
namespace {
#define EXPECT_VK_SUCCESS(value) EXPECT_EQ(vk::Result::eSuccess, (value))
class ProtectedMode : public testing::Test {
public:
bool Initialize();
protected:
std::unique_ptr<VulkanContext> ctx_;
bool device_supports_protected_memory_ = false;
vk::DispatchLoaderDynamic loader_;
};
bool ProtectedMode::Initialize() {
constexpr size_t kPhysicalDeviceIndex = 0;
vk::ApplicationInfo app_info;
app_info.pApplicationName = "vkext";
app_info.apiVersion = VK_API_VERSION_1_1;
vk::InstanceCreateInfo instance_info;
instance_info.pApplicationInfo = &app_info;
ctx_ = std::make_unique<VulkanContext>(kPhysicalDeviceIndex);
ctx_->set_instance_info(instance_info);
if (!ctx_->InitInstance()) {
return false;
}
loader_.init(*ctx_->instance(), vkGetInstanceProcAddr);
if (!ctx_->InitQueueFamily()) {
return false;
}
// Set |device_supports_protected_memory_| flag.
vk::PhysicalDeviceProtectedMemoryFeatures protected_memory(VK_TRUE);
vk::PhysicalDeviceProperties physical_device_properties;
ctx_->physical_device().getProperties(&physical_device_properties);
if (VK_VERSION_MAJOR(physical_device_properties.apiVersion) != 1 ||
VK_VERSION_MINOR(physical_device_properties.apiVersion) > 0) {
vk::PhysicalDeviceFeatures2 features2;
features2.pNext = &protected_memory;
ctx_->physical_device().getFeatures2(&features2);
if (protected_memory.protectedMemory) {
device_supports_protected_memory_ = true;
}
}
vk::DeviceCreateInfo device_info;
device_info.pNext = &protected_memory;
vk::DeviceQueueCreateInfo queue_info = ctx_->queue_info();
queue_info.flags = vk::DeviceQueueCreateFlagBits::eProtected;
device_info.setQueueCreateInfos(queue_info);
ctx_->set_device_info(device_info);
if (!ctx_->InitDevice()) {
return false;
}
return true;
}
struct BufferData {
vk::UniqueBuffer buffer;
vk::UniqueDeviceMemory device_memory;
};
BufferData CreateProtectedBuffer(vk::Device device, size_t size) {
BufferData buffer_data;
auto [buffer_res, buffer] =
device.createBufferUnique(vk::BufferCreateInfo()
.setSize(size)
.setUsage(vk::BufferUsageFlagBits::eTransferDst)
.setFlags(vk::BufferCreateFlagBits::eProtected));
EXPECT_EQ(buffer_res, vk::Result::eSuccess);
auto buffer_requirements = device.getBufferMemoryRequirements(*buffer);
uint32_t memory_type = __builtin_ctz(buffer_requirements.memoryTypeBits);
auto [memory_res, memory] =
device.allocateMemoryUnique(vk::MemoryAllocateInfo()
.setAllocationSize(buffer_requirements.size)
.setMemoryTypeIndex(memory_type));
EXPECT_EQ(memory_res, vk::Result::eSuccess);
EXPECT_VK_SUCCESS(device.bindBufferMemory(*buffer, *memory, 0));
buffer_data.buffer = std::move(buffer);
buffer_data.device_memory = std::move(memory);
return buffer_data;
}
// Check that HWCPipe doesn't hang even if the GPU is in protected mode.
TEST_F(ProtectedMode, PerformanceCounters) {
ASSERT_TRUE(Initialize());
if (!device_supports_protected_memory_) {
GTEST_SKIP();
}
auto [pool_res, command_pool] = ctx_->device()->createCommandPoolUnique(
vk::CommandPoolCreateInfo()
.setFlags(vk::CommandPoolCreateFlagBits::eProtected)
.setQueueFamilyIndex(ctx_->queue_family_index()));
EXPECT_EQ(vk::Result::eSuccess, pool_res);
std::vector<vk::UniqueCommandBuffer> command_buffers;
{
auto info = vk::CommandBufferAllocateInfo()
.setCommandPool(*command_pool)
.setLevel(vk::CommandBufferLevel::ePrimary)
.setCommandBufferCount(1);
auto result = ctx_->device()->allocateCommandBuffersUnique(info);
ASSERT_EQ(vk::Result::eSuccess, result.result);
command_buffers = std::move(result.value);
}
EXPECT_EQ(vk::Result::eSuccess, command_buffers[0]->begin(vk::CommandBufferBeginInfo()));
constexpr uint32_t kBufferSize = 1024;
auto buffer_data = CreateProtectedBuffer(*ctx_->device(), kBufferSize);
command_buffers[0]->fillBuffer(*buffer_data.buffer, 0, kBufferSize, 1);
EXPECT_EQ(vk::Result::eSuccess, command_buffers[0]->end());
// A protected submit should switch the GPU into protected mode.
vk::StructureChain<vk::SubmitInfo, vk::ProtectedSubmitInfo> submit_info;
submit_info.get<vk::SubmitInfo>().setCommandBuffers(*command_buffers[0]);
submit_info.get<vk::ProtectedSubmitInfo>().setProtectedSubmit(true);
EXPECT_EQ(vk::Result::eSuccess, ctx_->queue().submit(submit_info.get<vk::SubmitInfo>()));
EXPECT_VK_SUCCESS(ctx_->queue().waitIdle());
hwcpipe::HWCPipe pipe;
pipe.set_enabled_gpu_counters(pipe.gpu_profiler()->supported_counters());
// HWCPipe.run will start running and sample the performance counters initially.
pipe.run();
}
} // namespace