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 "util/random_utils.h"
13
14 using namespace rx;
15
16 namespace
17 {
18 constexpr unsigned int kIterationsPerStep = 100;
19
20 class VulkanPipelineCachePerfTest : public ANGLEPerfTest
21 {
22 public:
23 VulkanPipelineCachePerfTest();
24 ~VulkanPipelineCachePerfTest();
25
26 void SetUp() override;
27 void step() override;
28
29 GraphicsPipelineCache mCache;
30 angle::RNG mRNG;
31
32 std::vector<vk::GraphicsPipelineDesc> mCacheHits;
33 std::vector<vk::GraphicsPipelineDesc> mCacheMisses;
34 size_t mMissIndex = 0;
35
36 private:
37 void randomizeDesc(vk::GraphicsPipelineDesc *desc);
38 };
39
VulkanPipelineCachePerfTest()40 VulkanPipelineCachePerfTest::VulkanPipelineCachePerfTest()
41 : ANGLEPerfTest("VulkanPipelineCachePerf", "", "", kIterationsPerStep)
42 {}
43
~VulkanPipelineCachePerfTest()44 VulkanPipelineCachePerfTest::~VulkanPipelineCachePerfTest()
45 {
46 mCache.destroy(VK_NULL_HANDLE);
47 }
48
SetUp()49 void VulkanPipelineCachePerfTest::SetUp()
50 {
51 // Insert a number of random pipeline states.
52 for (int pipelineCount = 0; pipelineCount < 100; ++pipelineCount)
53 {
54 vk::Pipeline pipeline;
55 vk::GraphicsPipelineDesc desc;
56 randomizeDesc(&desc);
57
58 if (pipelineCount < 10)
59 {
60 mCacheHits.push_back(desc);
61 }
62 mCache.populate(desc, std::move(pipeline));
63 }
64
65 for (int missCount = 0; missCount < 10000; ++missCount)
66 {
67 vk::GraphicsPipelineDesc desc;
68 randomizeDesc(&desc);
69 mCacheMisses.push_back(desc);
70 }
71 }
72
randomizeDesc(vk::GraphicsPipelineDesc * desc)73 void VulkanPipelineCachePerfTest::randomizeDesc(vk::GraphicsPipelineDesc *desc)
74 {
75 std::vector<uint8_t> bytes(sizeof(vk::GraphicsPipelineDesc));
76 FillVectorWithRandomUBytes(&mRNG, &bytes);
77 memcpy(desc, bytes.data(), sizeof(vk::GraphicsPipelineDesc));
78 }
79
step()80 void VulkanPipelineCachePerfTest::step()
81 {
82 vk::RenderPass rp;
83 vk::PipelineLayout pl;
84 vk::PipelineCache pc;
85 vk::ShaderModule sm;
86 const vk::GraphicsPipelineDesc *desc = nullptr;
87 vk::PipelineHelper *result = nullptr;
88 gl::AttributesMask am;
89 gl::ComponentTypeMask ctm;
90
91 vk::SpecializationConstantBitSet defaultSpecConsts;
92
93 for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration)
94 {
95 for (const auto &hit : mCacheHits)
96 {
97 (void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, ctm, &sm, &sm, nullptr,
98 defaultSpecConsts, hit, &desc, &result);
99 }
100 }
101
102 for (int missCount = 0; missCount < 20 && mMissIndex < mCacheMisses.size();
103 ++missCount, ++mMissIndex)
104 {
105 const auto &miss = mCacheMisses[mMissIndex];
106 (void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, ctm, &sm, &sm, nullptr,
107 defaultSpecConsts, miss, &desc, &result);
108 }
109 }
110
111 } // anonymous namespace
112
TEST_F(VulkanPipelineCachePerfTest,Run)113 TEST_F(VulkanPipelineCachePerfTest, Run)
114 {
115 run();
116 }
117