Commit 4346c8b1 by Fei Yang Committed by Commit Bot

Vulkan: pipeline cache not populated as blob cache is not set

1. Use vkMergePipelineCaches to recreate pipeline cache after blob cache callbacks are set after eglInititalize. 2. Use a more proper way to save the cache data to disk. Bug: angleproject:3318 Change-Id: Ied1fb572813198b51e02ed9629cbf34e2d9159b2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1683807 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent a25c15c5
...@@ -141,8 +141,10 @@ class ProgramVk : public ProgramImpl ...@@ -141,8 +141,10 @@ class ProgramVk : public ProgramImpl
ANGLE_TRY(initGraphicsShaders(contextVk, mode, &shaderProgram)); ANGLE_TRY(initGraphicsShaders(contextVk, mode, &shaderProgram));
ASSERT(shaderProgram->isGraphicsProgram()); ASSERT(shaderProgram->isGraphicsProgram());
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
vk::PipelineCache *pipelineCache = nullptr;
ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
return shaderProgram->getGraphicsPipeline( return shaderProgram->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), renderer->getPipelineCache(), contextVk, &contextVk->getRenderPassCache(), *pipelineCache,
contextVk->getCurrentQueueSerial(), mPipelineLayout.get(), desc, activeAttribLocations, contextVk->getCurrentQueueSerial(), mPipelineLayout.get(), desc, activeAttribLocations,
mState.getAttributesTypeMask(), descPtrOut, pipelineOut); mState.getAttributesTypeMask(), descPtrOut, pipelineOut);
} }
......
...@@ -47,8 +47,8 @@ namespace rx ...@@ -47,8 +47,8 @@ namespace rx
namespace namespace
{ {
// Update the pipeline cache every this many swaps (if 60fps, this means every 10 minutes) // Update the pipeline cache every this many swaps.
constexpr uint32_t kPipelineCacheVkUpdatePeriod = 10 * 60 * 60; constexpr uint32_t kPipelineCacheVkUpdatePeriod = 60;
// Wait a maximum of 10s. If that times out, we declare it a failure. // Wait a maximum of 10s. If that times out, we declare it a failure.
constexpr uint64_t kMaxFenceWaitTimeNs = 10'000'000'000llu; constexpr uint64_t kMaxFenceWaitTimeNs = 10'000'000'000llu;
// Per the Vulkan specification, as long as Vulkan 1.1+ is returned by vkEnumerateInstanceVersion, // Per the Vulkan specification, as long as Vulkan 1.1+ is returned by vkEnumerateInstanceVersion,
...@@ -496,7 +496,9 @@ RendererVk::RendererVk() ...@@ -496,7 +496,9 @@ RendererVk::RendererVk()
mMaxVertexAttribDivisor(1), mMaxVertexAttribDivisor(1),
mDevice(VK_NULL_HANDLE), mDevice(VK_NULL_HANDLE),
mDeviceLost(false), mDeviceLost(false),
mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod) mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod),
mPipelineCacheDirty(false),
mPipelineCacheInitialized(false)
{ {
VkFormatProperties invalid = {0, 0, kInvalidFormatFeatureFlags}; VkFormatProperties invalid = {0, 0, kInvalidFormatFeatureFlags};
mFormatProperties.fill(invalid); mFormatProperties.fill(invalid);
...@@ -1026,7 +1028,8 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -1026,7 +1028,8 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
vkGetDeviceQueue(mDevice, mCurrentQueueFamilyIndex, 0, &mQueue); vkGetDeviceQueue(mDevice, mCurrentQueueFamilyIndex, 0, &mQueue);
// Initialize the vulkan pipeline cache. // Initialize the vulkan pipeline cache.
ANGLE_TRY(initPipelineCache(displayVk)); bool success = false;
ANGLE_TRY(initPipelineCache(displayVk, &mPipelineCache, &success));
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1315,22 +1318,49 @@ void RendererVk::initPipelineCacheVkKey() ...@@ -1315,22 +1318,49 @@ void RendererVk::initPipelineCacheVkKey()
hashString.length(), mPipelineCacheVkBlobKey.data()); hashString.length(), mPipelineCacheVkBlobKey.data());
} }
angle::Result RendererVk::initPipelineCache(DisplayVk *display) angle::Result RendererVk::initPipelineCache(DisplayVk *display,
vk::PipelineCache *pipelineCache,
bool *success)
{ {
initPipelineCacheVkKey(); initPipelineCacheVkKey();
egl::BlobCache::Value initialData; egl::BlobCache::Value initialData;
bool success = display->getBlobCache()->get(display->getScratchBuffer(), *success = display->getBlobCache()->get(display->getScratchBuffer(), mPipelineCacheVkBlobKey,
mPipelineCacheVkBlobKey, &initialData); &initialData);
VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {}; VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
pipelineCacheCreateInfo.flags = 0; pipelineCacheCreateInfo.flags = 0;
pipelineCacheCreateInfo.initialDataSize = success ? initialData.size() : 0; pipelineCacheCreateInfo.initialDataSize = *success ? initialData.size() : 0;
pipelineCacheCreateInfo.pInitialData = success ? initialData.data() : nullptr; pipelineCacheCreateInfo.pInitialData = *success ? initialData.data() : nullptr;
ANGLE_VK_TRY(display, pipelineCache->init(mDevice, pipelineCacheCreateInfo));
ANGLE_VK_TRY(display, mPipelineCache.init(mDevice, pipelineCacheCreateInfo)); return angle::Result::Continue;
}
angle::Result RendererVk::getPipelineCache(vk::PipelineCache **pipelineCache)
{
if (mPipelineCacheInitialized)
{
*pipelineCache = &mPipelineCache;
return angle::Result::Continue;
}
// We should now recreate the pipeline cache with the blob cache pipeline data.
vk::PipelineCache pCache;
bool success = false;
ANGLE_TRY(initPipelineCache(vk::GetImpl(mDisplay), &pCache, &success));
if (success)
{
// Merge the newly created pipeline cache into the existing one.
mPipelineCache.merge(mDevice, mPipelineCache.getHandle(), 1, pCache.ptr());
}
mPipelineCacheInitialized = true;
pCache.destroy(mDevice);
*pipelineCache = &mPipelineCache;
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1387,6 +1417,11 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk) ...@@ -1387,6 +1417,11 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk)
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
if (!mPipelineCacheDirty)
{
mPipelineCacheVkUpdateTimeout = kPipelineCacheVkUpdatePeriod;
return angle::Result::Continue;
}
mPipelineCacheVkUpdateTimeout = kPipelineCacheVkUpdatePeriod; mPipelineCacheVkUpdateTimeout = kPipelineCacheVkUpdatePeriod;
...@@ -1420,6 +1455,7 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk) ...@@ -1420,6 +1455,7 @@ angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk)
} }
displayVk->getBlobCache()->putApplication(mPipelineCacheVkBlobKey, *pipelineCacheData); displayVk->getBlobCache()->putApplication(mPipelineCacheVkBlobKey, *pipelineCacheData);
mPipelineCacheDirty = false;
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -128,8 +128,6 @@ class RendererVk : angle::NonCopyable ...@@ -128,8 +128,6 @@ class RendererVk : angle::NonCopyable
bool isMockICDEnabled() const { return mEnableMockICD; } bool isMockICDEnabled() const { return mEnableMockICD; }
const vk::PipelineCache &getPipelineCache() const { return mPipelineCache; }
// Query the format properties for select bits (linearTilingFeatures, optimalTilingFeatures and // Query the format properties for select bits (linearTilingFeatures, optimalTilingFeatures and
// bufferFeatures). Looks through mandatory features first, and falls back to querying the // bufferFeatures). Looks through mandatory features first, and falls back to querying the
// device (first time only). // device (first time only).
...@@ -160,13 +158,18 @@ class RendererVk : angle::NonCopyable ...@@ -160,13 +158,18 @@ class RendererVk : angle::NonCopyable
static constexpr size_t kMaxExtensionNames = 200; static constexpr size_t kMaxExtensionNames = 200;
using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>; using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
angle::Result getPipelineCache(vk::PipelineCache **pipelineCache);
void onNewGraphicsPipeline() { mPipelineCacheDirty = true; }
private: private:
angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex); angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
void ensureCapsInitialized() const; void ensureCapsInitialized() const;
void initFeatures(const ExtensionNameList &extensions); void initFeatures(const ExtensionNameList &extensions);
void initPipelineCacheVkKey(); void initPipelineCacheVkKey();
angle::Result initPipelineCache(DisplayVk *display); angle::Result initPipelineCache(DisplayVk *display,
vk::PipelineCache *pipelineCache,
bool *success);
template <VkFormatFeatureFlags VkFormatProperties::*features> template <VkFormatFeatureFlags VkFormatProperties::*features>
VkFormatFeatureFlags getFormatFeatureBits(VkFormat format, VkFormatFeatureFlags getFormatFeatureBits(VkFormat format,
...@@ -223,6 +226,8 @@ class RendererVk : angle::NonCopyable ...@@ -223,6 +226,8 @@ class RendererVk : angle::NonCopyable
vk::PipelineCache mPipelineCache; vk::PipelineCache mPipelineCache;
egl::BlobCache::Key mPipelineCacheVkBlobKey; egl::BlobCache::Key mPipelineCacheVkBlobKey;
uint32_t mPipelineCacheVkUpdateTimeout; uint32_t mPipelineCacheVkUpdateTimeout;
bool mPipelineCacheDirty;
bool mPipelineCacheInitialized;
// A cache of VkFormatProperties as queried from the device over time. // A cache of VkFormatProperties as queried from the device over time.
std::array<VkFormatProperties, vk::kNumVkFormats> mFormatProperties; std::array<VkFormatProperties, vk::kNumVkFormats> mFormatProperties;
......
...@@ -587,11 +587,12 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk, ...@@ -587,11 +587,12 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
// This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check. // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
const vk::GraphicsPipelineDesc *descPtr; const vk::GraphicsPipelineDesc *descPtr;
vk::PipelineHelper *helper; vk::PipelineHelper *helper;
vk::PipelineCache *pipelineCache = nullptr;
ANGLE_TRY(program->getGraphicsPipeline( ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
contextVk, &contextVk->getRenderPassCache(), renderer->getPipelineCache(), serial, ANGLE_TRY(program->getGraphicsPipeline(contextVk, &contextVk->getRenderPassCache(),
pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), gl::ComponentTypeMask(), *pipelineCache, serial, pipelineLayout.get(),
&descPtr, &helper)); *pipelineDesc, gl::AttributesMask(),
gl::ComponentTypeMask(), &descPtr, &helper));
helper->updateSerial(serial); helper->updateSerial(serial);
commandBuffer->bindGraphicsPipeline(helper->getPipeline()); commandBuffer->bindGraphicsPipeline(helper->getPipeline());
} }
......
...@@ -1705,6 +1705,7 @@ angle::Result GraphicsPipelineCache::insertPipeline( ...@@ -1705,6 +1705,7 @@ angle::Result GraphicsPipelineCache::insertPipeline(
// This "if" is left here for the benefit of VulkanPipelineCachePerfTest. // This "if" is left here for the benefit of VulkanPipelineCachePerfTest.
if (context != nullptr) if (context != nullptr)
{ {
context->getRenderer()->onNewGraphicsPipeline();
ANGLE_TRY(desc.initializePipeline(context, pipelineCacheVk, compatibleRenderPass, ANGLE_TRY(desc.initializePipeline(context, pipelineCacheVk, compatibleRenderPass,
pipelineLayout, activeAttribLocationsMask, pipelineLayout, activeAttribLocationsMask,
programAttribsTypeMask, vertexModule, fragmentModule, programAttribsTypeMask, vertexModule, fragmentModule,
......
...@@ -2752,8 +2752,10 @@ angle::Result ShaderProgramHelper::getComputePipeline(Context *context, ...@@ -2752,8 +2752,10 @@ angle::Result ShaderProgramHelper::getComputePipeline(Context *context,
createInfo.basePipelineHandle = VK_NULL_HANDLE; createInfo.basePipelineHandle = VK_NULL_HANDLE;
createInfo.basePipelineIndex = 0; createInfo.basePipelineIndex = 0;
vk::PipelineCache *pipelineCache = nullptr;
ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
ANGLE_VK_TRY(context, mComputePipeline.get().initCompute(context->getDevice(), createInfo, ANGLE_VK_TRY(context, mComputePipeline.get().initCompute(context->getDevice(), createInfo,
renderer->getPipelineCache())); *pipelineCache));
*pipelineOut = &mComputePipeline; *pipelineOut = &mComputePipeline;
return angle::Result::Continue; return angle::Result::Continue;
......
...@@ -478,6 +478,10 @@ class PipelineCache final : public WrappedObject<PipelineCache, VkPipelineCache> ...@@ -478,6 +478,10 @@ class PipelineCache final : public WrappedObject<PipelineCache, VkPipelineCache>
VkResult init(VkDevice device, const VkPipelineCacheCreateInfo &createInfo); VkResult init(VkDevice device, const VkPipelineCacheCreateInfo &createInfo);
VkResult getCacheData(VkDevice device, size_t *cacheSize, void *cacheData); VkResult getCacheData(VkDevice device, size_t *cacheSize, void *cacheData);
VkResult merge(VkDevice device,
VkPipelineCache dstCache,
uint32_t srcCacheCount,
const VkPipelineCache *srcCaches);
}; };
class DescriptorSetLayout final : public WrappedObject<DescriptorSetLayout, VkDescriptorSetLayout> class DescriptorSetLayout final : public WrappedObject<DescriptorSetLayout, VkDescriptorSetLayout>
...@@ -1237,6 +1241,15 @@ ANGLE_INLINE VkResult PipelineCache::init(VkDevice device, ...@@ -1237,6 +1241,15 @@ ANGLE_INLINE VkResult PipelineCache::init(VkDevice device,
return vkCreatePipelineCache(device, &createInfo, nullptr, &mHandle); return vkCreatePipelineCache(device, &createInfo, nullptr, &mHandle);
} }
ANGLE_INLINE VkResult PipelineCache::merge(VkDevice device,
VkPipelineCache dstCache,
uint32_t srcCacheCount,
const VkPipelineCache *srcCaches)
{
ASSERT(valid());
return vkMergePipelineCaches(device, dstCache, srcCacheCount, srcCaches);
}
ANGLE_INLINE VkResult PipelineCache::getCacheData(VkDevice device, ANGLE_INLINE VkResult PipelineCache::getCacheData(VkDevice device,
size_t *cacheSize, size_t *cacheSize,
void *cacheData) void *cacheData)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment