[dxvk] Removed on-disk pipeline cache

Drivers from both major vendors implement their own shader cache
already, and storing a cache per game causes more issues than it
solves. Should fix #261.
This commit is contained in:
Philip Rebohle 2018-04-09 19:38:32 +02:00
parent 8a4e1d11b7
commit d68d62f837
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
7 changed files with 4 additions and 222 deletions

View File

@ -107,8 +107,6 @@ namespace dxvk {
auto t1 = std::chrono::high_resolution_clock::now();
auto td = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
Logger::debug(str::format("DxvkComputePipeline: Finished in ", td.count(), " ms"));
m_cache->update();
return pipeline;
}

View File

@ -184,7 +184,6 @@ namespace dxvk {
DxvkStatCounters result;
result.setCtr(DxvkStatCounter::MemoryAllocated, mem.memoryAllocated);
result.setCtr(DxvkStatCounter::MemoryUsed, mem.memoryUsed);
result.setCtr(DxvkStatCounter::PipeCacheSize, m_pipelineCache->getCacheSize());
std::lock_guard<sync::Spinlock> lock(m_statLock);
result.merge(m_statCounters);

View File

@ -265,8 +265,6 @@ namespace dxvk {
auto t1 = std::chrono::high_resolution_clock::now();
auto td = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
Logger::debug(str::format("DxvkGraphicsPipeline: Finished in ", td.count(), " ms"));
m_cache->update();
return pipeline;
}

View File

@ -4,19 +4,13 @@ namespace dxvk {
DxvkPipelineCache::DxvkPipelineCache(
const Rc<vk::DeviceFn>& vkd)
: m_vkd (vkd),
m_fileName (getFileName()),
m_updateStop (0),
m_updateCounter (0),
m_updateThread ([this] { this->runThread(); }) {
auto initialData = this->loadPipelineCache();
: m_vkd(vkd) {
VkPipelineCacheCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.initialDataSize = initialData.size();
info.pInitialData = initialData.data();
info.initialDataSize = 0;
info.pInitialData = nullptr;
if (m_vkd->vkCreatePipelineCache(m_vkd->device(),
&info, nullptr, &m_handle) != VK_SUCCESS)
@ -25,167 +19,8 @@ namespace dxvk {
DxvkPipelineCache::~DxvkPipelineCache() {
// Stop the shader cache update thread
{ std::unique_lock<std::mutex> lock(m_updateMutex);
m_updateStop = -1;
m_updateCond.notify_one();
}
m_updateThread.join();
// Make sure we store the full cache again
this->storePipelineCache(
this->getPipelineCache());
m_vkd->vkDestroyPipelineCache(
m_vkd->device(), m_handle, nullptr);
}
void DxvkPipelineCache::update() {
m_updateCounter += 1;
}
size_t DxvkPipelineCache::getCacheSize() const {
size_t cacheSize = 0;
m_vkd->vkGetPipelineCacheData(
m_vkd->device(), m_handle, &cacheSize, nullptr);
return cacheSize;
}
void DxvkPipelineCache::runThread() {
uint32_t prevUpdateCounter = 0;
uint32_t currUpdateCounter = 0;
while (true) {
// Periodically check whether we need to update once a minute.
// We don't want to write the full pipeline cache with every
// single update because that would cause unnecessary load.
{ std::unique_lock<std::mutex> lock(m_updateMutex);
bool exit = m_updateCond.wait_for(lock,
std::chrono::seconds(60),
[this] { return m_updateStop != 0; });
if (exit)
return;
}
// Only update the cache if new pipelines
// have been created in the meantime
currUpdateCounter = m_updateCounter.load();
if (currUpdateCounter != prevUpdateCounter) {
prevUpdateCounter = currUpdateCounter;
this->storePipelineCache(this->getPipelineCache());
}
}
}
std::vector<char> DxvkPipelineCache::getPipelineCache() const {
std::vector<char> cacheData;
VkResult status = VK_INCOMPLETE;
while (status == VK_INCOMPLETE) {
size_t cacheSize = 0;
if (m_vkd->vkGetPipelineCacheData(m_vkd->device(),
m_handle, &cacheSize, nullptr) != VK_SUCCESS) {
Logger::warn("DxvkPipelineCache: Failed to retrieve cache size");
break;
}
cacheData.resize(cacheSize);
status = m_vkd->vkGetPipelineCacheData(m_vkd->device(),
m_handle, &cacheSize, cacheData.data());
}
if (status != VK_SUCCESS) {
Logger::warn("DxvkPipelineCache: Failed to retrieve cache data");
cacheData.resize(0);
}
return cacheData;
}
std::vector<char> DxvkPipelineCache::loadPipelineCache() const {
std::vector<char> cacheData;
if (m_fileName.size() == 0) {
Logger::warn("DxvkPipelineCache: Failed to locate cache file");
return cacheData;
}
auto cacheFile = std::ifstream(m_fileName,
std::ios_base::binary | std::ios_base::ate);
if (!cacheFile.good()) {
Logger::warn("DxvkPipelineCache: Failed to read cache file");
return cacheData;
}
std::streamsize cacheSize = cacheFile.tellg();
cacheFile.seekg(0, std::ios_base::beg);
cacheData.resize(cacheSize);
if (!cacheFile.read(cacheData.data(), cacheData.size())) {
Logger::warn("DxvkPipelineCache: Failed to read cache file");
cacheData.resize(0);
}
Logger::debug(str::format(
"DxvkPipelineCache: Read ", cacheData.size(),
" bytes from ", m_fileName));
return cacheData;
}
void DxvkPipelineCache::storePipelineCache(const std::vector<char>& cacheData) const {
if (m_fileName.size() == 0) {
Logger::warn("DxvkPipelineCache: Failed to locate cache file");
return;
}
auto cacheFile = std::ofstream(m_fileName,
std::ios_base::binary | std::ios_base::trunc);
if (!cacheFile.good()) {
Logger::warn("DxvkPipelineCache: Failed to open cache file");
return;
}
cacheFile.write(cacheData.data(), cacheData.size());
if (!cacheFile.good()) {
Logger::warn("DxvkPipelineCache: Failed to write shader cache file");
return;
}
Logger::debug(str::format(
"DxvkPipelineCache: Wrote ", cacheData.size(),
" bytes to ", m_fileName));
}
std::string DxvkPipelineCache::getFileName() {
const auto exeName = env::getExeName();
const auto filename = Sha1Hash::compute(
reinterpret_cast<const uint8_t*>(exeName.c_str()), exeName.size());
const auto temp = env::getTempDirectory();
if (temp.size() != 0)
return str::format(temp, filename.toString(), ".pipecache");
return std::string();
}
}

View File

@ -34,45 +34,11 @@ namespace dxvk {
return m_handle;
}
/**
* \brief Sends an update signal
*
* Notifies the update thread that the
* pipeline cache should be updated.
*/
void update();
/**
* \brief Queries pipeline cache size
* \returns Cache size, in bytes
*/
size_t getCacheSize() const;
private:
Rc<vk::DeviceFn> m_vkd;
VkPipelineCache m_handle;
std::string m_fileName;
std::atomic<uint32_t> m_updateStop;
std::atomic<uint32_t> m_updateCounter;
std::mutex m_updateMutex;
std::condition_variable m_updateCond;
std::thread m_updateThread;
void runThread();
std::vector<char> getPipelineCache() const;
std::vector<char> loadPipelineCache() const;
void storePipelineCache(
const std::vector<char>& cacheData) const;
static std::string getFileName();
};
}

View File

@ -19,7 +19,6 @@ namespace dxvk {
MemoryUsed, ///< Amount of memory used
PipeCountGraphics, ///< Number of graphics pipelines
PipeCountCompute, ///< Number of compute pipelines
PipeCacheSize, ///< Pipeline cache size
QueueSubmitCount, ///< Number of command buffer submissions
QueuePresentCount, ///< Number of present calls / frames
NumCounters, ///< Number of counters available

View File

@ -98,20 +98,12 @@ namespace dxvk::hud {
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position) {
constexpr uint64_t kib = 1024;
constexpr uint64_t mib = 1024 * 1024;
const uint64_t gpCount = m_prevCounters.getCtr(DxvkStatCounter::PipeCountGraphics);
const uint64_t cpCount = m_prevCounters.getCtr(DxvkStatCounter::PipeCountCompute);
const uint64_t pcSize = m_prevCounters.getCtr(DxvkStatCounter::PipeCacheSize);
const std::string strGpCount = str::format("Graphics pipelines: ", gpCount);
const std::string strCpCount = str::format("Compute pipelines: ", cpCount);
const std::string strPcSize = str::format("Pipeline cache: ", pcSize >= mib
? str::format(pcSize / mib, ".", ((10 * pcSize) / mib) % 10, " MB")
: str::format(pcSize / kib, " kB"));
renderer.drawText(context, 16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
@ -122,12 +114,7 @@ namespace dxvk::hud {
{ 1.0f, 1.0f, 1.0f, 1.0f },
strCpCount);
renderer.drawText(context, 16.0f,
{ position.x, position.y + 40.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strPcSize);
return { position.x, position.y + 64.0f };
return { position.x, position.y + 44.0f };
}