1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00
OpenDX/src/dxvk/dxvk_state_cache.h
2019-05-06 03:15:45 +02:00

176 lines
4.7 KiB
C++

#pragma once
#include <atomic>
#include <condition_variable>
#include <fstream>
#include <mutex>
#include <queue>
#include <unordered_map>
#include <vector>
#include "dxvk_state_cache_types.h"
namespace dxvk {
class DxvkDevice;
/**
* \brief State cache
*
* The shader state cache stores state vectors and
* render pass formats of all pipelines used in a
* game, which allows DXVK to compile them ahead
* of time instead of compiling them on the first
* draw.
*/
class DxvkStateCache : public RcObject {
public:
DxvkStateCache(
const DxvkDevice* device,
DxvkPipelineManager* pipeManager,
DxvkRenderPassPool* passManager);
~DxvkStateCache();
/**
* Adds a graphics pipeline to the cache
*
* If the pipeline is not already cached, this
* will write a new pipeline to the cache file.
* \param [in] shaders Shader keys
* \param [in] state Graphics pipeline state
* \param [in] format Render pass format
*/
void addGraphicsPipeline(
const DxvkStateCacheKey& shaders,
const DxvkGraphicsPipelineStateInfo& state,
const DxvkRenderPassFormat& format);
/**
* Adds a compute pipeline to the cache
*
* If the pipeline is not already cached, this
* will write a new pipeline to the cache file.
* \param [in] shaders Shader keys
* \param [in] state Compute pipeline state
*/
void addComputePipeline(
const DxvkStateCacheKey& shaders,
const DxvkComputePipelineStateInfo& state);
/**
* \brief Registers a newly compiled shader
*
* Makes the shader available to the pipeline
* compiler, and starts compiling all pipelines
* for which all shaders become available.
* \param [in] shader The shader to add
*/
void registerShader(
const Rc<DxvkShader>& shader);
/**
* \brief Checks whether compiler threads are busy
* \returns \c true if we're compiling shaders
*/
bool isCompilingShaders() {
return m_workerBusy.load() > 0;
}
private:
using WriterItem = DxvkStateCacheEntry;
struct WorkerItem {
Rc<DxvkShader> vs;
Rc<DxvkShader> tcs;
Rc<DxvkShader> tes;
Rc<DxvkShader> gs;
Rc<DxvkShader> fs;
Rc<DxvkShader> cs;
};
DxvkPipelineManager* m_pipeManager;
DxvkRenderPassPool* m_passManager;
std::vector<DxvkStateCacheEntry> m_entries;
std::atomic<bool> m_stopThreads = { false };
std::mutex m_entryLock;
std::unordered_multimap<
DxvkStateCacheKey, size_t,
DxvkHash, DxvkEq> m_entryMap;
std::unordered_multimap<
DxvkShaderKey, DxvkStateCacheKey,
DxvkHash, DxvkEq> m_pipelineMap;
std::unordered_map<
DxvkShaderKey, Rc<DxvkShader>,
DxvkHash, DxvkEq> m_shaderMap;
std::mutex m_workerLock;
std::condition_variable m_workerCond;
std::queue<WorkerItem> m_workerQueue;
std::atomic<uint32_t> m_workerBusy;
std::vector<dxvk::thread> m_workerThreads;
std::mutex m_writerLock;
std::condition_variable m_writerCond;
std::queue<WriterItem> m_writerQueue;
dxvk::thread m_writerThread;
DxvkShaderKey getShaderKey(
const Rc<DxvkShader>& shader) const;
bool getShaderByKey(
const DxvkShaderKey& key,
Rc<DxvkShader>& shader) const;
void mapPipelineToEntry(
const DxvkStateCacheKey& key,
size_t entryId);
void mapShaderToPipeline(
const DxvkShaderKey& shader,
const DxvkStateCacheKey& key);
void compilePipelines(
const WorkerItem& item);
bool readCacheFile();
bool readCacheHeader(
std::istream& stream,
DxvkStateCacheHeader& header) const;
bool readCacheEntry(
uint32_t version,
std::istream& stream,
DxvkStateCacheEntry& entry) const;
void writeCacheEntry(
std::ostream& stream,
DxvkStateCacheEntry& entry) const;
bool convertEntryV2(
DxvkStateCacheEntryV4& entry) const;
bool convertEntryV4(
const DxvkStateCacheEntryV4& in,
DxvkStateCacheEntry& out) const;
void workerFunc();
void writerFunc();
std::string getCacheFileName() const;
std::string getCacheDir() const;
};
}