Hash :
adde4265
Author :
Date :
2022-10-19T23:33:48
Vulkan: Separate pipeline cache query and insertion In preparation for VK_EXT_graphics_pipeline_library usage, the query and insertion functions of the graphics pipeline cache are separated. This will allow the implementation using VK_EXT_graphics_pipeline_library to query the monolithic pipeline cache, and if a pipeline is not found, create it through the pipeline library caches. Bug: angleproject:7369 Change-Id: Iebf7669ae3ea95e180646198c4861cc59d67e580 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3963854 Reviewed-by: Charlie Lao <cclao@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com>
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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VulkanPipelineCachePerf:
// Performance benchmark for the Vulkan Pipeline cache.
#include "ANGLEPerfTest.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "util/random_utils.h"
using namespace rx;
namespace
{
constexpr unsigned int kIterationsPerStep = 100;
struct Params
{
bool withDynamicState = false;
};
class VulkanPipelineCachePerfTest : public ANGLEPerfTest,
public ::testing::WithParamInterface<Params>
{
public:
VulkanPipelineCachePerfTest();
~VulkanPipelineCachePerfTest();
void SetUp() override;
void step() override;
GraphicsPipelineCache<GraphicsPipelineDescCompleteHash> mCache;
angle::RNG mRNG;
std::vector<vk::GraphicsPipelineDesc> mCacheHits;
std::vector<vk::GraphicsPipelineDesc> mCacheMisses;
size_t mMissIndex = 0;
private:
void randomizeDesc(vk::GraphicsPipelineDesc *desc);
};
VulkanPipelineCachePerfTest::VulkanPipelineCachePerfTest()
: ANGLEPerfTest("VulkanPipelineCachePerf", "", "", kIterationsPerStep), mRNG(0x12345678u)
{}
VulkanPipelineCachePerfTest::~VulkanPipelineCachePerfTest()
{
mCache.reset();
}
void VulkanPipelineCachePerfTest::SetUp()
{
// Insert a number of random pipeline states.
for (int pipelineCount = 0; pipelineCount < 100; ++pipelineCount)
{
vk::Pipeline pipeline;
vk::GraphicsPipelineDesc desc;
randomizeDesc(&desc);
if (pipelineCount < 10)
{
mCacheHits.push_back(desc);
}
mCache.populate(desc, std::move(pipeline));
}
for (int missCount = 0; missCount < 10000; ++missCount)
{
vk::GraphicsPipelineDesc desc;
randomizeDesc(&desc);
mCacheMisses.push_back(desc);
}
}
void VulkanPipelineCachePerfTest::randomizeDesc(vk::GraphicsPipelineDesc *desc)
{
std::vector<uint8_t> bytes(sizeof(vk::GraphicsPipelineDesc));
FillVectorWithRandomUBytes(&mRNG, &bytes);
memcpy(desc, bytes.data(), sizeof(vk::GraphicsPipelineDesc));
desc->setSupportsDynamicStateForTest(GetParam().withDynamicState);
}
void VulkanPipelineCachePerfTest::step()
{
vk::RenderPass rp;
vk::PipelineLayout pl;
vk::PipelineCache pc;
PipelineCacheAccess spc;
vk::RefCounted<vk::ShaderAndSerial> vsAndSerial;
vk::RefCounted<vk::ShaderAndSerial> fsAndSerial;
vk::ShaderAndSerialMap ssm;
const vk::GraphicsPipelineDesc *desc = nullptr;
vk::PipelineHelper *result = nullptr;
// The Vulkan handle types are difficult to cast to without #ifdefs.
VkShaderModule vs = (VkShaderModule)1;
VkShaderModule fs = (VkShaderModule)2;
vsAndSerial.get().get().setHandle(vs);
fsAndSerial.get().get().setHandle(fs);
ssm[gl::ShaderType::Vertex].set(&vsAndSerial);
ssm[gl::ShaderType::Fragment].set(&fsAndSerial);
spc.init(&pc, nullptr);
vk::SpecializationConstants defaultSpecConsts{};
for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration)
{
for (const auto &hit : mCacheHits)
{
if (!mCache.getPipeline(hit, &desc, &result))
{
(void)mCache.createPipeline(VK_NULL_HANDLE, &spc, rp, pl, ssm, defaultSpecConsts,
PipelineSource::Draw, hit, &desc, &result);
}
}
}
for (int missCount = 0; missCount < 20 && mMissIndex < mCacheMisses.size();
++missCount, ++mMissIndex)
{
const auto &miss = mCacheMisses[mMissIndex];
if (!mCache.getPipeline(miss, &desc, &result))
{
(void)mCache.createPipeline(VK_NULL_HANDLE, &spc, rp, pl, ssm, defaultSpecConsts,
PipelineSource::Draw, miss, &desc, &result);
}
}
vsAndSerial.get().get().setHandle(VK_NULL_HANDLE);
fsAndSerial.get().get().setHandle(VK_NULL_HANDLE);
}
} // anonymous namespace
// Test performance of pipeline hash and look up in Vulkan
TEST_P(VulkanPipelineCachePerfTest, Run)
{
run();
}
INSTANTIATE_TEST_SUITE_P(,
VulkanPipelineCachePerfTest,
::testing::ValuesIn(std::vector<Params>{{Params{false}, Params{true}}}));