зеркало из https://github.com/AvaloniaUI/angle.git
Vulkan: Add a perf test for the Pipeline cache.
This micro-benchmark can be used to measure the performance impact of changing the Pipeline cache. For instance, we can check if changing the size of the hash key affects performance significantly. Also updates the build files so angle_perftests can see vulkan.h, and makes the Vulkan headers an explicit source set. This test currently shows that a lot of time is spent in PMurmurHash, with some time also spent in memcmp. Bug: angleproject:2163 Change-Id: Ie8bb3e31d58590f373d28cbbb59f7e372b80cc29 Reviewed-on: https://chromium-review.googlesource.com/884882 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Родитель
12c0376106
Коммит
5dd4ad896b
1
BUILD.gn
1
BUILD.gn
|
@ -506,6 +506,7 @@ static_library("libANGLE") {
|
|||
sources += rebase_path(gles_gypi.libangle_vulkan_xcb_sources, ".", "src")
|
||||
}
|
||||
deps += [ "src/vulkan_support:angle_vulkan" ]
|
||||
public_deps += [ "src/vulkan_support:vulkan_headers" ]
|
||||
}
|
||||
|
||||
if (angle_enable_null) {
|
||||
|
|
|
@ -793,8 +793,13 @@ vk::Error PipelineCache::getPipeline(VkDevice device,
|
|||
}
|
||||
|
||||
vk::Pipeline newPipeline;
|
||||
ANGLE_TRY(desc.initializePipeline(device, compatibleRenderPass, pipelineLayout, vertexModule,
|
||||
fragmentModule, &newPipeline));
|
||||
|
||||
// This "if" is left here for the benefit of VulkanPipelineCachePerfTest.
|
||||
if (device != VK_NULL_HANDLE)
|
||||
{
|
||||
ANGLE_TRY(desc.initializePipeline(device, compatibleRenderPass, pipelineLayout,
|
||||
vertexModule, fragmentModule, &newPipeline));
|
||||
}
|
||||
|
||||
// The Serial will be updated outside of this query.
|
||||
auto insertedItem =
|
||||
|
@ -804,4 +809,15 @@ vk::Error PipelineCache::getPipeline(VkDevice device,
|
|||
return vk::NoError();
|
||||
}
|
||||
|
||||
void PipelineCache::populate(const vk::PipelineDesc &desc, vk::Pipeline &&pipeline)
|
||||
{
|
||||
auto item = mPayload.find(desc);
|
||||
if (item != mPayload.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mPayload.emplace(desc, vk::PipelineAndSerial(std::move(pipeline), Serial()));
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -384,6 +384,7 @@ class PipelineCache final : angle::NonCopyable
|
|||
|
||||
void destroy(VkDevice device);
|
||||
|
||||
void populate(const vk::PipelineDesc &desc, vk::Pipeline &&pipeline);
|
||||
vk::Error getPipeline(VkDevice device,
|
||||
const vk::RenderPass &compatibleRenderPass,
|
||||
const vk::PipelineLayout &pipelineLayout,
|
||||
|
|
|
@ -259,6 +259,12 @@ if (is_win || is_linux || is_android || is_mac) {
|
|||
rebase_path(perftests_gypi.angle_perf_tests_win_sources, ".", "../..")
|
||||
}
|
||||
|
||||
if (angle_enable_vulkan) {
|
||||
sources += rebase_path(perftests_gypi.angle_perf_tests_vulkan_sources,
|
||||
".",
|
||||
"../..")
|
||||
}
|
||||
|
||||
if (build_with_chromium) {
|
||||
sources += [ "//gpu/angle_perftests_main.cc" ]
|
||||
} else {
|
||||
|
|
|
@ -50,7 +50,12 @@
|
|||
'angle_perf_tests_win_sources':
|
||||
[
|
||||
'<(angle_path)/src/tests/perf_tests/IndexDataManagerTest.cpp',
|
||||
]
|
||||
],
|
||||
# Only enabled with angle_enable_vulkan. Not exposed in the gyp.
|
||||
'angle_perf_tests_vulkan_sources':
|
||||
[
|
||||
'<(angle_path)/src/tests/perf_tests/VulkanPipelineCachePerf.cpp',
|
||||
],
|
||||
},
|
||||
# Everything below (except WinRT-related config) must be also maintained for GN.
|
||||
# If you change anything below, also update angle/src/tests/BUILD.gn.
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
//
|
||||
// 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/vk_cache_utils.h"
|
||||
#include "random_utils.h"
|
||||
|
||||
using namespace rx;
|
||||
|
||||
namespace
|
||||
{
|
||||
class VulkanPipelineCachePerfTest : public ANGLEPerfTest
|
||||
{
|
||||
public:
|
||||
VulkanPipelineCachePerfTest();
|
||||
~VulkanPipelineCachePerfTest();
|
||||
|
||||
void SetUp() override;
|
||||
void step() override;
|
||||
|
||||
PipelineCache mCache;
|
||||
angle::RNG mRNG;
|
||||
|
||||
std::vector<vk::PipelineDesc> mCacheHits;
|
||||
std::vector<vk::PipelineDesc> mCacheMisses;
|
||||
size_t mMissIndex = 0;
|
||||
|
||||
private:
|
||||
void randomizeDesc(vk::PipelineDesc *desc);
|
||||
};
|
||||
|
||||
VulkanPipelineCachePerfTest::VulkanPipelineCachePerfTest()
|
||||
: ANGLEPerfTest("VulkanPipelineCachePerf", "")
|
||||
{
|
||||
}
|
||||
|
||||
VulkanPipelineCachePerfTest::~VulkanPipelineCachePerfTest()
|
||||
{
|
||||
mCache.destroy(VK_NULL_HANDLE);
|
||||
}
|
||||
|
||||
void VulkanPipelineCachePerfTest::SetUp()
|
||||
{
|
||||
// Insert a number of random pipeline states.
|
||||
for (int pipelineCount = 0; pipelineCount < 100; ++pipelineCount)
|
||||
{
|
||||
vk::Pipeline pipeline;
|
||||
vk::PipelineDesc desc;
|
||||
randomizeDesc(&desc);
|
||||
|
||||
if (pipelineCount < 10)
|
||||
{
|
||||
mCacheHits.push_back(desc);
|
||||
}
|
||||
mCache.populate(desc, std::move(pipeline));
|
||||
}
|
||||
|
||||
for (int missCount = 0; missCount < 10000; ++missCount)
|
||||
{
|
||||
vk::PipelineDesc desc;
|
||||
randomizeDesc(&desc);
|
||||
mCacheMisses.push_back(desc);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanPipelineCachePerfTest::randomizeDesc(vk::PipelineDesc *desc)
|
||||
{
|
||||
std::vector<uint8_t> bytes(sizeof(vk::PipelineDesc));
|
||||
FillVectorWithRandomUBytes(&mRNG, &bytes);
|
||||
memcpy(desc, bytes.data(), sizeof(vk::PipelineDesc));
|
||||
}
|
||||
|
||||
void VulkanPipelineCachePerfTest::step()
|
||||
{
|
||||
vk::RenderPass rp;
|
||||
vk::PipelineLayout pl;
|
||||
vk::ShaderModule sm;
|
||||
vk::PipelineAndSerial *result = nullptr;
|
||||
|
||||
for (int iteration = 0; iteration < 100; ++iteration)
|
||||
{
|
||||
for (const auto &hit : mCacheHits)
|
||||
{
|
||||
(void)mCache.getPipeline(VK_NULL_HANDLE, rp, pl, sm, sm, hit, &result);
|
||||
}
|
||||
}
|
||||
|
||||
for (int missCount = 0; missCount < 20 && mMissIndex < mCacheMisses.size();
|
||||
++missCount, ++mMissIndex)
|
||||
{
|
||||
const auto &miss = mCacheMisses[mMissIndex];
|
||||
(void)mCache.getPipeline(VK_NULL_HANDLE, rp, pl, sm, sm, miss, &result);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
TEST_F(VulkanPipelineCachePerfTest, Run)
|
||||
{
|
||||
run();
|
||||
}
|
|
@ -181,18 +181,33 @@ if (spirv_use_commit_id) {
|
|||
}
|
||||
}
|
||||
|
||||
config("vulkan_generate_helper_files_config") {
|
||||
include_dirs = [
|
||||
vulkan_gen_dir,
|
||||
"$vulkan_layers_dir/include",
|
||||
config("vulkan_headers_config") {
|
||||
include_dirs = [ "$vulkan_layers_dir/include" ]
|
||||
}
|
||||
|
||||
# Vulkan headers only, no compiled sources.
|
||||
source_set("vulkan_headers") {
|
||||
sources = [
|
||||
"$vulkan_layers_dir/include/vulkan/vk_icd.h",
|
||||
"$vulkan_layers_dir/include/vulkan/vk_layer.h",
|
||||
"$vulkan_layers_dir/include/vulkan/vk_platform.h",
|
||||
"$vulkan_layers_dir/include/vulkan/vk_sdk_platform.h",
|
||||
"$vulkan_layers_dir/include/vulkan/vulkan.h",
|
||||
"$vulkan_layers_dir/include/vulkan/vulkan.hpp",
|
||||
]
|
||||
public_configs = [ ":vulkan_headers_config" ]
|
||||
}
|
||||
|
||||
config("vulkan_generated_files_config") {
|
||||
include_dirs = [ vulkan_gen_dir ]
|
||||
}
|
||||
|
||||
group("vulkan_generate_helper_files") {
|
||||
public_deps = [
|
||||
":spirv_tools_external_revision_generate",
|
||||
":vulkan_headers",
|
||||
]
|
||||
public_configs = [ ":vulkan_generate_helper_files_config" ]
|
||||
public_configs = [ ":vulkan_generated_files_config" ]
|
||||
foreach(script_and_dep, helper_script_and_deps) {
|
||||
target_name = script_and_dep[0]
|
||||
public_deps += [ ":$target_name" ]
|
||||
|
@ -301,6 +316,9 @@ static_library("vulkan_loader") {
|
|||
deps = [
|
||||
":vulkan_generate_helper_files",
|
||||
]
|
||||
public_deps = [
|
||||
":vulkan_headers",
|
||||
]
|
||||
configs += [ ":vulkan_internal_config" ]
|
||||
public_configs = [
|
||||
":vulkan_config",
|
||||
|
@ -894,6 +912,9 @@ group("angle_vulkan") {
|
|||
":glslang",
|
||||
":vulkan_loader",
|
||||
]
|
||||
public_deps = [
|
||||
":vulkan_headers",
|
||||
]
|
||||
data_deps = [
|
||||
":vulkan_gen_json_files",
|
||||
]
|
||||
|
|
|
@ -40,14 +40,19 @@ class ANGLE_EXPORT RNG
|
|||
std::default_random_engine mGenerator;
|
||||
};
|
||||
|
||||
// Implemented htis way because of cross-module allocation issues.
|
||||
// Implemented inline to avoid cross-module allocation issues.
|
||||
inline void FillVectorWithRandomUBytes(RNG *rng, std::vector<uint8_t> *data)
|
||||
{
|
||||
for (size_t i = 0; i < data->size(); ++i)
|
||||
{
|
||||
(*data)[i] = static_cast<uint8_t>(rng->randomIntBetween(0, 255));
|
||||
}
|
||||
}
|
||||
|
||||
inline void FillVectorWithRandomUBytes(std::vector<uint8_t> *data)
|
||||
{
|
||||
RNG rng;
|
||||
for (size_t i = 0; i < data->size(); ++i)
|
||||
{
|
||||
(*data)[i] = static_cast<uint8_t>(rng.randomIntBetween(0, 255));
|
||||
}
|
||||
FillVectorWithRandomUBytes(&rng, data);
|
||||
}
|
||||
|
||||
} // namespace angle
|
||||
|
|
Загрузка…
Ссылка в новой задаче