Add ability to write out VkPipelineCache to gpu PersistentCache.
Bug: skia:
Change-Id: Id13d680401f69a074ae0c85f9ceaf3308fccb129
Reviewed-on: https://skia-review.googlesource.com/c/181403
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp
index 060bc87..5ca2330 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -36,22 +36,55 @@
delete fPipelineStateCache;
}
-void GrVkResourceProvider::init() {
- VkPipelineCacheCreateInfo createInfo;
- memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
- createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
- createInfo.pNext = nullptr;
- createInfo.flags = 0;
- createInfo.initialDataSize = 0;
- createInfo.pInitialData = nullptr;
- VkResult result = GR_VK_CALL(fGpu->vkInterface(),
- CreatePipelineCache(fGpu->device(), &createInfo, nullptr,
- &fPipelineCache));
- SkASSERT(VK_SUCCESS == result);
- if (VK_SUCCESS != result) {
- fPipelineCache = VK_NULL_HANDLE;
- }
+VkPipelineCache GrVkResourceProvider::pipelineCache() {
+ if (fPipelineCache == VK_NULL_HANDLE) {
+ VkPipelineCacheCreateInfo createInfo;
+ memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
+ createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ createInfo.pNext = nullptr;
+ createInfo.flags = 0;
+ auto persistentCache = fGpu->getContext()->contextPriv().getPersistentCache();
+ sk_sp<SkData> cached;
+ if (persistentCache) {
+ uint32_t key = GrVkGpu::kPipelineCache_PersistentCacheKeyType;
+ sk_sp<SkData> keyData = SkData::MakeWithoutCopy(&key, sizeof(uint32_t));
+ cached = persistentCache->load(*keyData);
+ }
+ bool usedCached = false;
+ if (cached) {
+ uint32_t* cacheHeader = (uint32_t*)cached->data();
+ if (cacheHeader[1] == VK_PIPELINE_CACHE_HEADER_VERSION_ONE) {
+ // For version one of the header, the total header size is 16 bytes plus
+ // VK_UUID_SIZE bytes. See Section 9.6 (Pipeline Cache) in the vulkan spec to see
+ // the breakdown of these bytes.
+ SkASSERT(cacheHeader[0] == 16 + VK_UUID_SIZE);
+ const VkPhysicalDeviceProperties& devProps = fGpu->physicalDeviceProperties();
+ const uint8_t* supportedPipelineCacheUUID = devProps.pipelineCacheUUID;
+ if (cacheHeader[2] == devProps.vendorID && cacheHeader[3] == devProps.deviceID &&
+ !memcmp(&cacheHeader[4], supportedPipelineCacheUUID, VK_UUID_SIZE)) {
+ createInfo.initialDataSize = cached->size();
+ createInfo.pInitialData = cached->data();
+ usedCached = true;
+ }
+ }
+ }
+ if (!usedCached) {
+ createInfo.initialDataSize = 0;
+ createInfo.pInitialData = nullptr;
+ }
+ VkResult result = GR_VK_CALL(fGpu->vkInterface(),
+ CreatePipelineCache(fGpu->device(), &createInfo, nullptr,
+ &fPipelineCache));
+ SkASSERT(VK_SUCCESS == result);
+ if (VK_SUCCESS != result) {
+ fPipelineCache = VK_NULL_HANDLE;
+ }
+ }
+ return fPipelineCache;
+}
+
+void GrVkResourceProvider::init() {
// Init uniform descriptor objects
GrVkDescriptorSetManager* dsm = GrVkDescriptorSetManager::CreateUniformManager(fGpu);
fDescriptorSetManagers.emplace_back(dsm);
@@ -69,7 +102,7 @@
VkPipelineLayout layout) {
return GrVkPipeline::Create(fGpu, primProc, pipeline, stencil, shaderStageInfo,
shaderStageCount, primitiveType, compatibleRenderPass, layout,
- fPipelineCache);
+ this->pipelineCache());
}
GrVkCopyPipeline* GrVkResourceProvider::findOrCreateCopyPipeline(
@@ -88,7 +121,7 @@
pipelineLayout,
dst->numColorSamples(),
*dst->simpleRenderPass(),
- fPipelineCache);
+ this->pipelineCache());
if (!pipeline) {
return nullptr;
}
@@ -491,6 +524,28 @@
fAvailableCommandPools.push_back(pool);
}
+void GrVkResourceProvider::storePipelineCacheData() {
+ size_t dataSize = 0;
+ VkResult result = GR_VK_CALL(fGpu->vkInterface(), GetPipelineCacheData(fGpu->device(),
+ this->pipelineCache(),
+ &dataSize, nullptr));
+ SkASSERT(result == VK_SUCCESS);
+
+ std::unique_ptr<uint8_t[]> data(new uint8_t[dataSize]);
+
+ result = GR_VK_CALL(fGpu->vkInterface(), GetPipelineCacheData(fGpu->device(),
+ this->pipelineCache(),
+ &dataSize,
+ (void*)data.get()));
+ SkASSERT(result == VK_SUCCESS);
+
+ uint32_t key = GrVkGpu::kPipelineCache_PersistentCacheKeyType;
+ sk_sp<SkData> keyData = SkData::MakeWithoutCopy(&key, sizeof(uint32_t));
+
+ fGpu->getContext()->contextPriv().getPersistentCache()->store(
+ *keyData, *SkData::MakeWithoutCopy(data.get(), dataSize));
+}
+
////////////////////////////////////////////////////////////////////////////////
GrVkResourceProvider::CompatibleRenderPassSet::CompatibleRenderPassSet(