| // | |
| // 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 "common/unsafe_buffers.h" | |
| #include "libANGLE/renderer/vulkan/vk_cache_utils.h" | |
| #include "libANGLE/renderer/vulkan/vk_helpers.h" | |
| #include "libANGLE/renderer/vulkan/vk_renderer.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() | |
| { | |
| ANGLEPerfTest::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), nullptr); | |
| } | |
| 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); | |
| ANGLE_UNSAFE_TODO(memcpy(desc, bytes.data(), sizeof(vk::GraphicsPipelineDesc))); | |
| desc->setSupportsDynamicStateForTest(GetParam().withDynamicState); | |
| } | |
| void VulkanPipelineCachePerfTest::step() | |
| { | |
| vk::RenderPass rp; | |
| vk::PipelineLayout pl; | |
| vk::PipelineCache pc; | |
| vk::PipelineCacheAccess spc; | |
| vk::ShaderModulePtr vs = vk::ShaderModulePtr::MakeShared(VK_NULL_HANDLE); | |
| vk::ShaderModulePtr fs = vk::ShaderModulePtr::MakeShared(VK_NULL_HANDLE); | |
| vk::ShaderModuleMap ssm; | |
| const vk::GraphicsPipelineDesc *desc = nullptr; | |
| vk::PipelineHelper *result = nullptr; | |
| // The Vulkan handle types are difficult to cast to without #ifdefs. | |
| vs->setHandle((VkShaderModule)1); | |
| fs->setHandle((VkShaderModule)2); | |
| ssm[gl::ShaderType::Vertex] = vs; | |
| ssm[gl::ShaderType::Fragment] = fs; | |
| spc.init(&pc, nullptr); | |
| 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}, | |
| 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}, PipelineSource::Draw, | |
| miss, &desc, &result); | |
| } | |
| } | |
| vs->setHandle(VK_NULL_HANDLE); | |
| fs->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}}})); |