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>
This commit is contained in:
parent
f1202c61de
commit
a870b46c79
@ -1517,6 +1517,9 @@ Error GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
|
||||
context->contextPriv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
|
||||
}
|
||||
}
|
||||
if (grOptions.fPersistentCache) {
|
||||
context->storeVkPipelineCacheData();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -283,6 +283,8 @@ public:
|
||||
|
||||
bool supportsDistanceFieldText() const;
|
||||
|
||||
void storeVkPipelineCacheData();
|
||||
|
||||
protected:
|
||||
GrContext(GrBackendApi, int32_t id = SK_InvalidGenID);
|
||||
|
||||
|
@ -397,6 +397,16 @@ void GrContextPriv::flush(GrSurfaceProxy* proxy) {
|
||||
fContext->fDrawingManager->flush(proxy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrContext::storeVkPipelineCacheData() {
|
||||
if (fGpu) {
|
||||
fGpu->storeVkPipelineCacheData();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: This will be removed when GrSurfaceContexts are aware of their color types.
|
||||
// (skbug.com/6718)
|
||||
static bool valid_premul_config(GrPixelConfig config) {
|
||||
|
@ -429,6 +429,8 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void storeVkPipelineCacheData() {}
|
||||
|
||||
protected:
|
||||
// Handles cases where a surface will be updated without a call to flushRenderTarget.
|
||||
void didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
|
||||
|
@ -170,10 +170,11 @@ GrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
|
||||
VK_CALL(GetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &fPhysDevProps));
|
||||
VK_CALL(GetPhysicalDeviceMemoryProperties(backendContext.fPhysicalDevice, &fPhysDevMemProps));
|
||||
|
||||
fResourceProvider.init();
|
||||
|
||||
fCmdPool = fResourceProvider.findOrCreateCommandPool();
|
||||
fCurrentCmdBuffer = fCmdPool->getPrimaryCommandBuffer();
|
||||
SkASSERT(fCurrentCmdBuffer);
|
||||
fResourceProvider.init();
|
||||
fCurrentCmdBuffer->begin(this);
|
||||
}
|
||||
|
||||
@ -2203,3 +2204,9 @@ uint32_t GrVkGpu::getExtraSamplerKeyForProgram(const GrSamplerState& samplerStat
|
||||
return sampler->uniqueID();
|
||||
}
|
||||
|
||||
void GrVkGpu::storeVkPipelineCacheData() {
|
||||
if (this->getContext()->contextPriv().getPersistentCache()) {
|
||||
this->resourceProvider().storePipelineCacheData();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,10 +57,10 @@ public:
|
||||
VkQueue queue() const { return fQueue; }
|
||||
uint32_t queueIndex() const { return fQueueIndex; }
|
||||
GrVkCommandPool* cmdPool() const { return fCmdPool; }
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties() const {
|
||||
const VkPhysicalDeviceProperties& physicalDeviceProperties() const {
|
||||
return fPhysDevProps;
|
||||
}
|
||||
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties() const {
|
||||
const VkPhysicalDeviceMemoryProperties& physicalDeviceMemoryProperties() const {
|
||||
return fPhysDevMemProps;
|
||||
}
|
||||
|
||||
@ -166,6 +166,13 @@ public:
|
||||
uint32_t getExtraSamplerKeyForProgram(const GrSamplerState&,
|
||||
const GrBackendFormat& format) override;
|
||||
|
||||
enum PersistentCacheKeyType : uint32_t {
|
||||
kShader_PersistentCacheKeyType = 0,
|
||||
kPipelineCache_PersistentCacheKeyType = 1,
|
||||
};
|
||||
|
||||
void storeVkPipelineCacheData() override;
|
||||
|
||||
private:
|
||||
GrVkGpu(GrContext*, const GrContextOptions&, const GrVkBackendContext&,
|
||||
sk_sp<const GrVkInterface>);
|
||||
|
@ -183,8 +183,10 @@ void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String& vert,
|
||||
const SkSL::Program::Inputs& fragInputs,
|
||||
const SkSL::String& geom,
|
||||
const SkSL::Program::Inputs& geomInputs) {
|
||||
Desc* desc = static_cast<Desc*>(this->desc());
|
||||
|
||||
// see loadShadersFromCache for the layout of cache entries
|
||||
sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
|
||||
sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
|
||||
size_t dataLength = (sizeof(shader_size) + sizeof(SkSL::Program::Inputs)) * 3 + vert.length() +
|
||||
frag.length() + geom.length();
|
||||
std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]);
|
||||
@ -276,7 +278,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
|
||||
sk_sp<SkData> cached;
|
||||
auto persistentCache = fGpu->getContext()->contextPriv().getPersistentCache();
|
||||
if (persistentCache) {
|
||||
sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->keyLength());
|
||||
sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
|
||||
cached = persistentCache->load(*key);
|
||||
}
|
||||
int numShaderStages;
|
||||
@ -395,6 +397,12 @@ bool GrVkPipelineStateBuilder::Desc::Build(Desc* desc,
|
||||
}
|
||||
|
||||
GrProcessorKeyBuilder b(&desc->key());
|
||||
|
||||
b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
|
||||
int keyLength = desc->key().count();
|
||||
SkASSERT(0 == (keyLength % 4));
|
||||
desc->fShaderKeyLength = SkToU32(keyLength);
|
||||
|
||||
GrVkRenderTarget* vkRT = (GrVkRenderTarget*)pipeline.renderTarget();
|
||||
vkRT->simpleRenderPass()->genKey(&b);
|
||||
|
||||
|
@ -44,7 +44,11 @@ public:
|
||||
GrPrimitiveType primitiveType,
|
||||
GrVkGpu* gpu);
|
||||
|
||||
size_t shaderKeyLength() const { return fShaderKeyLength; }
|
||||
|
||||
private:
|
||||
size_t fShaderKeyLength;
|
||||
|
||||
typedef GrProgramDesc INHERITED;
|
||||
};
|
||||
|
||||
|
@ -36,22 +36,55 @@ GrVkResourceProvider::~GrVkResourceProvider() {
|
||||
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 @@ GrVkPipeline* GrVkResourceProvider::createPipeline(const GrPrimitiveProcessor& p
|
||||
VkPipelineLayout layout) {
|
||||
return GrVkPipeline::Create(fGpu, primProc, pipeline, stencil, shaderStageInfo,
|
||||
shaderStageCount, primitiveType, compatibleRenderPass, layout,
|
||||
fPipelineCache);
|
||||
this->pipelineCache());
|
||||
}
|
||||
|
||||
GrVkCopyPipeline* GrVkResourceProvider::findOrCreateCopyPipeline(
|
||||
@ -88,7 +121,7 @@ GrVkCopyPipeline* GrVkResourceProvider::findOrCreateCopyPipeline(
|
||||
pipelineLayout,
|
||||
dst->numColorSamples(),
|
||||
*dst->simpleRenderPass(),
|
||||
fPipelineCache);
|
||||
this->pipelineCache());
|
||||
if (!pipeline) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -491,6 +524,28 @@ void GrVkResourceProvider::reset(GrVkCommandPool* pool) {
|
||||
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(
|
||||
|
@ -156,6 +156,8 @@ public:
|
||||
// can be reused by the next uniform buffer resource request.
|
||||
void recycleStandardUniformBufferResource(const GrVkResource*);
|
||||
|
||||
void storePipelineCacheData();
|
||||
|
||||
// Destroy any cached resources. To be called before destroying the VkDevice.
|
||||
// The assumption is that all queues are idle and all command buffers are finished.
|
||||
// For resource tracing to work properly, this should be called after unrefing all other
|
||||
@ -245,6 +247,8 @@ private:
|
||||
int fLastReturnedIndex;
|
||||
};
|
||||
|
||||
VkPipelineCache pipelineCache();
|
||||
|
||||
GrVkGpu* fGpu;
|
||||
|
||||
// Central cache for creating pipelines
|
||||
|
Loading…
Reference in New Issue
Block a user