xref: /aosp_15_r20/external/angle/src/tests/perf_tests/VulkanPipelineCachePerf.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // VulkanPipelineCachePerf:
7 //   Performance benchmark for the Vulkan Pipeline cache.
8 
9 #include "ANGLEPerfTest.h"
10 
11 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
12 #include "libANGLE/renderer/vulkan/vk_helpers.h"
13 #include "libANGLE/renderer/vulkan/vk_renderer.h"
14 #include "util/random_utils.h"
15 
16 using namespace rx;
17 
18 namespace
19 {
20 constexpr unsigned int kIterationsPerStep = 100;
21 
22 struct Params
23 {
24     bool withDynamicState = false;
25 };
26 
27 class VulkanPipelineCachePerfTest : public ANGLEPerfTest,
28                                     public ::testing::WithParamInterface<Params>
29 {
30   public:
31     VulkanPipelineCachePerfTest();
32     ~VulkanPipelineCachePerfTest();
33 
34     void SetUp() override;
35     void step() override;
36 
37     GraphicsPipelineCache<GraphicsPipelineDescCompleteHash> mCache;
38     angle::RNG mRNG;
39 
40     std::vector<vk::GraphicsPipelineDesc> mCacheHits;
41     std::vector<vk::GraphicsPipelineDesc> mCacheMisses;
42     size_t mMissIndex = 0;
43 
44   private:
45     void randomizeDesc(vk::GraphicsPipelineDesc *desc);
46 };
47 
VulkanPipelineCachePerfTest()48 VulkanPipelineCachePerfTest::VulkanPipelineCachePerfTest()
49     : ANGLEPerfTest("VulkanPipelineCachePerf", "", "", kIterationsPerStep), mRNG(0x12345678u)
50 {}
51 
~VulkanPipelineCachePerfTest()52 VulkanPipelineCachePerfTest::~VulkanPipelineCachePerfTest()
53 {
54     mCache.reset();
55 }
56 
SetUp()57 void VulkanPipelineCachePerfTest::SetUp()
58 {
59     ANGLEPerfTest::SetUp();
60 
61     // Insert a number of random pipeline states.
62     for (int pipelineCount = 0; pipelineCount < 100; ++pipelineCount)
63     {
64         vk::Pipeline pipeline;
65         vk::GraphicsPipelineDesc desc;
66         randomizeDesc(&desc);
67 
68         if (pipelineCount < 10)
69         {
70             mCacheHits.push_back(desc);
71         }
72         mCache.populate(desc, std::move(pipeline), nullptr);
73     }
74 
75     for (int missCount = 0; missCount < 10000; ++missCount)
76     {
77         vk::GraphicsPipelineDesc desc;
78         randomizeDesc(&desc);
79         mCacheMisses.push_back(desc);
80     }
81 }
82 
randomizeDesc(vk::GraphicsPipelineDesc * desc)83 void VulkanPipelineCachePerfTest::randomizeDesc(vk::GraphicsPipelineDesc *desc)
84 {
85     std::vector<uint8_t> bytes(sizeof(vk::GraphicsPipelineDesc));
86     FillVectorWithRandomUBytes(&mRNG, &bytes);
87     memcpy(desc, bytes.data(), sizeof(vk::GraphicsPipelineDesc));
88 
89     desc->setSupportsDynamicStateForTest(GetParam().withDynamicState);
90 }
91 
step()92 void VulkanPipelineCachePerfTest::step()
93 {
94     vk::RenderPass rp;
95     vk::PipelineLayout pl;
96     vk::PipelineCache pc;
97     vk::PipelineCacheAccess spc;
98     vk::ShaderModulePtr vs = vk::ShaderModulePtr::MakeShared(VK_NULL_HANDLE);
99     vk::ShaderModulePtr fs = vk::ShaderModulePtr::MakeShared(VK_NULL_HANDLE);
100     vk::ShaderModuleMap ssm;
101     const vk::GraphicsPipelineDesc *desc = nullptr;
102     vk::PipelineHelper *result           = nullptr;
103 
104     // The Vulkan handle types are difficult to cast to without #ifdefs.
105     vs->setHandle((VkShaderModule)1);
106     fs->setHandle((VkShaderModule)2);
107 
108     ssm[gl::ShaderType::Vertex]   = vs;
109     ssm[gl::ShaderType::Fragment] = fs;
110 
111     spc.init(&pc, nullptr);
112 
113     vk::SpecializationConstants defaultSpecConsts{};
114 
115     for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration)
116     {
117         for (const auto &hit : mCacheHits)
118         {
119             if (!mCache.getPipeline(hit, &desc, &result))
120             {
121                 (void)mCache.createPipeline(VK_NULL_HANDLE, &spc, rp, pl, ssm, defaultSpecConsts,
122                                             PipelineSource::Draw, hit, &desc, &result);
123             }
124         }
125     }
126 
127     for (int missCount = 0; missCount < 20 && mMissIndex < mCacheMisses.size();
128          ++missCount, ++mMissIndex)
129     {
130         const auto &miss = mCacheMisses[mMissIndex];
131         if (!mCache.getPipeline(miss, &desc, &result))
132         {
133             (void)mCache.createPipeline(VK_NULL_HANDLE, &spc, rp, pl, ssm, defaultSpecConsts,
134                                         PipelineSource::Draw, miss, &desc, &result);
135         }
136     }
137 
138     vs->setHandle(VK_NULL_HANDLE);
139     fs->setHandle(VK_NULL_HANDLE);
140 }
141 
142 }  // anonymous namespace
143 
144 // Test performance of pipeline hash and look up in Vulkan
TEST_P(VulkanPipelineCachePerfTest,Run)145 TEST_P(VulkanPipelineCachePerfTest, Run)
146 {
147     run();
148 }
149 
150 INSTANTIATE_TEST_SUITE_P(,
151                          VulkanPipelineCachePerfTest,
152                          ::testing::ValuesIn(std::vector<Params>{{Params{false}, Params{true}}}));
153