blob: 83664b68af92e6c40cdab1ffb4ff4d87a2ac436d [file] [log] [blame]
Alexis Hetu18a84252018-11-19 11:30:43 -05001// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef VK_PIPELINE_CACHE_HPP_
16#define VK_PIPELINE_CACHE_HPP_
17
18#include "VkObject.hpp"
Ben Clayton4d23aa32020-04-14 20:33:52 +010019#include "VkSpecializationInfo.hpp"
Ben Claytonfa0175c2019-07-30 11:49:08 +010020
Ben Clayton377573c2020-04-03 20:36:40 +010021#include "marl/mutex.h"
22#include "marl/tsa.h"
23
Alexis Hetu52edb172019-06-26 10:17:18 -040024#include <cstring>
25#include <functional>
Alexis Hetu52edb172019-06-26 10:17:18 -040026#include <map>
Ben Claytonfa0175c2019-07-30 11:49:08 +010027#include <memory>
Ben Claytonfa0175c2019-07-30 11:49:08 +010028#include <string>
Alexis Hetu52edb172019-06-26 10:17:18 -040029#include <vector>
30
Nicolas Capens157ba262019-12-10 17:49:14 -050031namespace sw {
Alexis Hetu18a84252018-11-19 11:30:43 -050032
Nicolas Capens157ba262019-12-10 17:49:14 -050033class ComputeProgram;
34class SpirvShader;
35
36} // namespace sw
37
38namespace vk {
Alexis Hetu18a84252018-11-19 11:30:43 -050039
Alexis Hetu52edb172019-06-26 10:17:18 -040040class PipelineLayout;
41class RenderPass;
42
Alexis Hetu18a84252018-11-19 11:30:43 -050043class PipelineCache : public Object<PipelineCache, VkPipelineCache>
44{
45public:
Ben Clayton2ed93ab2019-12-17 20:38:03 +000046 PipelineCache(const VkPipelineCacheCreateInfo *pCreateInfo, void *mem);
Alexis Hetu52edb172019-06-26 10:17:18 -040047 virtual ~PipelineCache();
Ben Clayton2ed93ab2019-12-17 20:38:03 +000048 void destroy(const VkAllocationCallbacks *pAllocator);
Alexis Hetu18a84252018-11-19 11:30:43 -050049
Ben Clayton2ed93ab2019-12-17 20:38:03 +000050 static size_t ComputeRequiredAllocationSize(const VkPipelineCacheCreateInfo *pCreateInfo);
Alexis Hetu1424ef62019-04-05 18:03:53 -040051
Ben Clayton2ed93ab2019-12-17 20:38:03 +000052 VkResult getData(size_t *pDataSize, void *pData);
53 VkResult merge(uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches);
Alexis Hetu18a84252018-11-19 11:30:43 -050054
Alexis Hetu52edb172019-06-26 10:17:18 -040055 struct SpirvShaderKey
56 {
Alexis Hetu52edb172019-06-26 10:17:18 -040057 SpirvShaderKey(const VkShaderStageFlagBits pipelineStage,
Ben Clayton2ed93ab2019-12-17 20:38:03 +000058 const std::string &entryPointName,
59 const std::vector<uint32_t> &insns,
Alexis Hetu52edb172019-06-26 10:17:18 -040060 const vk::RenderPass *renderPass,
61 const uint32_t subpassIndex,
Ben Clayton4d23aa32020-04-14 20:33:52 +010062 const vk::SpecializationInfo &specializationInfo);
Alexis Hetu52edb172019-06-26 10:17:18 -040063
64 bool operator<(const SpirvShaderKey &other) const;
65
Ben Clayton2ed93ab2019-12-17 20:38:03 +000066 const VkShaderStageFlagBits &getPipelineStage() const { return pipelineStage; }
67 const std::string &getEntryPointName() const { return entryPointName; }
68 const std::vector<uint32_t> &getInsns() const { return insns; }
Alexis Hetu52edb172019-06-26 10:17:18 -040069 const vk::RenderPass *getRenderPass() const { return renderPass; }
70 uint32_t getSubpassIndex() const { return subpassIndex; }
71 const VkSpecializationInfo *getSpecializationInfo() const { return specializationInfo.get(); }
72
73 private:
74 const VkShaderStageFlagBits pipelineStage;
75 const std::string entryPointName;
76 const std::vector<uint32_t> insns;
77 const vk::RenderPass *renderPass;
78 const uint32_t subpassIndex;
Ben Clayton4d23aa32020-04-14 20:33:52 +010079 const vk::SpecializationInfo specializationInfo;
Alexis Hetu52edb172019-06-26 10:17:18 -040080 };
81
Ben Clayton094974d2020-04-08 16:55:02 +010082 // getOrCreateShader() queries the cache for a shader with the given key.
83 // If one is found, it is returned, otherwise create() is called, the
84 // returned shader is added to the cache, and it is returned.
85 // Function must be a function of the signature:
86 // std::shared_ptr<sw::SpirvShader>()
87 template<typename Function>
88 inline std::shared_ptr<sw::SpirvShader> getOrCreateShader(const PipelineCache::SpirvShaderKey &key, Function &&create);
Alexis Hetu52edb172019-06-26 10:17:18 -040089
90 struct ComputeProgramKey
91 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +000092 ComputeProgramKey(const sw::SpirvShader *shader, const vk::PipelineLayout *layout)
93 : shader(shader)
94 , layout(layout)
Alexis Hetu52edb172019-06-26 10:17:18 -040095 {}
96
Ben Claytone6092f32019-07-29 19:44:13 +010097 bool operator<(const ComputeProgramKey &other) const
98 {
Antonio Maiorano126d9d62019-09-13 09:58:58 -040099 return std::tie(shader, layout) < std::tie(other.shader, other.layout);
Alexis Hetu52edb172019-06-26 10:17:18 -0400100 }
101
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000102 const sw::SpirvShader *getShader() const { return shader; }
103 const vk::PipelineLayout *getLayout() const { return layout; }
Alexis Hetu52edb172019-06-26 10:17:18 -0400104
105 private:
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000106 const sw::SpirvShader *shader;
107 const vk::PipelineLayout *layout;
Alexis Hetu52edb172019-06-26 10:17:18 -0400108 };
109
Ben Clayton094974d2020-04-08 16:55:02 +0100110 // getOrCreateComputeProgram() queries the cache for a compute program with
111 // the given key.
112 // If one is found, it is returned, otherwise create() is called, the
113 // returned program is added to the cache, and it is returned.
114 // Function must be a function of the signature:
115 // std::shared_ptr<sw::ComputeProgram>()
116 template<typename Function>
117 inline std::shared_ptr<sw::ComputeProgram> getOrCreateComputeProgram(const PipelineCache::ComputeProgramKey &key, Function &&create);
Alexis Hetu52edb172019-06-26 10:17:18 -0400118
Alexis Hetu18a84252018-11-19 11:30:43 -0500119private:
Alexis Hetu1424ef62019-04-05 18:03:53 -0400120 struct CacheHeader
121 {
122 uint32_t headerLength;
123 uint32_t headerVersion;
124 uint32_t vendorID;
125 uint32_t deviceID;
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000126 uint8_t pipelineCacheUUID[VK_UUID_SIZE];
Alexis Hetu1424ef62019-04-05 18:03:53 -0400127 };
128
129 size_t dataSize = 0;
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000130 uint8_t *data = nullptr;
Alexis Hetu52edb172019-06-26 10:17:18 -0400131
Ben Clayton377573c2020-04-03 20:36:40 +0100132 marl::mutex spirvShadersMutex;
133 std::map<SpirvShaderKey, std::shared_ptr<sw::SpirvShader>> spirvShaders GUARDED_BY(spirvShadersMutex);
Alexis Hetu52edb172019-06-26 10:17:18 -0400134
Ben Clayton377573c2020-04-03 20:36:40 +0100135 marl::mutex computeProgramsMutex;
136 std::map<ComputeProgramKey, std::shared_ptr<sw::ComputeProgram>> computePrograms GUARDED_BY(computeProgramsMutex);
Alexis Hetu18a84252018-11-19 11:30:43 -0500137};
138
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000139static inline PipelineCache *Cast(VkPipelineCache object)
Alexis Hetu18a84252018-11-19 11:30:43 -0500140{
Alexis Hetubd4cf812019-06-14 15:14:07 -0400141 return PipelineCache::Cast(object);
Alexis Hetu18a84252018-11-19 11:30:43 -0500142}
143
Ben Clayton094974d2020-04-08 16:55:02 +0100144template<typename Function>
145std::shared_ptr<sw::ComputeProgram> PipelineCache::getOrCreateComputeProgram(const PipelineCache::ComputeProgramKey &key, Function &&create)
146{
Ben Clayton377573c2020-04-03 20:36:40 +0100147 marl::lock lock(computeProgramsMutex);
Ben Clayton094974d2020-04-08 16:55:02 +0100148
149 auto it = computePrograms.find(key);
150 if(it != computePrograms.end()) { return it->second; }
151
152 auto created = create();
153 computePrograms.emplace(key, created);
154 return created;
155}
156
157template<typename Function>
158std::shared_ptr<sw::SpirvShader> PipelineCache::getOrCreateShader(const PipelineCache::SpirvShaderKey &key, Function &&create)
159{
Ben Clayton377573c2020-04-03 20:36:40 +0100160 marl::lock lock(spirvShadersMutex);
Ben Clayton094974d2020-04-08 16:55:02 +0100161
162 auto it = spirvShaders.find(key);
163 if(it != spirvShaders.end()) { return it->second; }
164
165 auto created = create();
166 spirvShaders.emplace(key, created);
167 return created;
168}
169
Nicolas Capens157ba262019-12-10 17:49:14 -0500170} // namespace vk
Alexis Hetu18a84252018-11-19 11:30:43 -0500171
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000172#endif // VK_PIPELINE_CACHE_HPP_