mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 13:08:50 +01:00
[dxvk] Add pre-rasterization pipeline libraries to the state cache
This allows compiling tessellation or geometry shader pipelines early while still using the pipeline library path. Also removes compute shaders. Since API-provided compute shaders are always compiled early, supporting them is no longer needed.
This commit is contained in:
parent
28ae85b7ab
commit
e5157a5360
@ -60,10 +60,8 @@ namespace dxvk {
|
||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||
instance = this->findInstance(state);
|
||||
|
||||
if (!instance) {
|
||||
if (!instance)
|
||||
instance = this->createInstance(state);
|
||||
this->writePipelineStateToCache(state);
|
||||
}
|
||||
}
|
||||
|
||||
return instance->handle;
|
||||
@ -139,17 +137,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkComputePipeline::writePipelineStateToCache(
|
||||
const DxvkComputePipelineStateInfo& state) const {
|
||||
DxvkStateCacheKey key;
|
||||
|
||||
if (m_shaders.cs != nullptr)
|
||||
key.cs = m_shaders.cs->getShaderKey();
|
||||
|
||||
m_stateCache->addComputePipeline(key, state);
|
||||
}
|
||||
|
||||
|
||||
void DxvkComputePipeline::logPipelineState(
|
||||
LogLevel level,
|
||||
const DxvkComputePipelineStateInfo& state) const {
|
||||
|
@ -149,9 +149,6 @@ namespace dxvk {
|
||||
void destroyPipeline(
|
||||
VkPipeline pipeline);
|
||||
|
||||
void writePipelineStateToCache(
|
||||
const DxvkComputePipelineStateInfo& state) const;
|
||||
|
||||
void logPipelineState(
|
||||
LogLevel level,
|
||||
const DxvkComputePipelineStateInfo& state) const;
|
||||
|
@ -297,12 +297,9 @@ namespace dxvk {
|
||||
DxvkShaderPipelineLibraryKey vsKey;
|
||||
vsKey.addShader(shaders.vs);
|
||||
|
||||
if (shaders.tcs != nullptr)
|
||||
vsKey.addShader(shaders.tcs);
|
||||
if (shaders.tes != nullptr)
|
||||
vsKey.addShader(shaders.tes);
|
||||
if (shaders.gs != nullptr)
|
||||
vsKey.addShader(shaders.gs);
|
||||
if (shaders.tcs != nullptr) vsKey.addShader(shaders.tcs);
|
||||
if (shaders.tes != nullptr) vsKey.addShader(shaders.tes);
|
||||
if (shaders.gs != nullptr) vsKey.addShader(shaders.gs);
|
||||
|
||||
if (vsKey.canUsePipelineLibrary()) {
|
||||
vsLibrary = findPipelineLibraryLocked(vsKey);
|
||||
@ -313,6 +310,17 @@ namespace dxvk {
|
||||
// Don't dispatch the pipeline library to a worker thread
|
||||
// since it should be compiled on demand anyway.
|
||||
vsLibrary = createPipelineLibraryLocked(vsKey);
|
||||
|
||||
// Register the pipeline library with the state cache
|
||||
// so that subsequent runs can still compile it early
|
||||
DxvkStateCacheKey shaderKeys;
|
||||
shaderKeys.vs = shaders.vs->getShaderKey();
|
||||
|
||||
if (shaders.tcs != nullptr) shaderKeys.tcs = shaders.tcs->getShaderKey();
|
||||
if (shaders.tes != nullptr) shaderKeys.tes = shaders.tes->getShaderKey();
|
||||
if (shaders.gs != nullptr) shaderKeys.gs = shaders.gs->getShaderKey();
|
||||
|
||||
m_stateCache.addPipelineLibrary(shaderKeys);
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,6 +343,13 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderPipelineLibrary* DxvkPipelineManager::createShaderPipelineLibrary(
|
||||
const DxvkShaderPipelineLibraryKey& key) {
|
||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||
return createPipelineLibraryLocked(key);
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipelineVertexInputLibrary* DxvkPipelineManager::createVertexInputLibrary(
|
||||
const DxvkGraphicsPipelineVertexInputState& state) {
|
||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||
@ -373,7 +388,7 @@ namespace dxvk {
|
||||
DxvkShaderPipelineLibraryKey key;
|
||||
key.addShader(shader);
|
||||
|
||||
auto library = createPipelineLibrary(key);
|
||||
auto library = createShaderPipelineLibrary(key);
|
||||
m_workers.compilePipelineLibrary(library, DxvkPipelinePriority::Normal);
|
||||
}
|
||||
|
||||
@ -452,13 +467,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderPipelineLibrary* DxvkPipelineManager::createPipelineLibrary(
|
||||
const DxvkShaderPipelineLibraryKey& key) {
|
||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||
return createPipelineLibraryLocked(key);
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderPipelineLibrary* DxvkPipelineManager::createPipelineLibraryLocked(
|
||||
const DxvkShaderPipelineLibraryKey& key) {
|
||||
auto bindings = key.getBindings();
|
||||
|
@ -185,6 +185,16 @@ namespace dxvk {
|
||||
DxvkGraphicsPipeline* createGraphicsPipeline(
|
||||
const DxvkGraphicsPipelineShaders& shaders);
|
||||
|
||||
/**
|
||||
* \brief Creates a pipeline library with a given set of shaders
|
||||
*
|
||||
* If a pipeline library already exists, it will be returned.
|
||||
* Otherwise, a new pipeline library will be created.
|
||||
* \param [in] key Shader set
|
||||
*/
|
||||
DxvkShaderPipelineLibrary* createShaderPipelineLibrary(
|
||||
const DxvkShaderPipelineLibraryKey& key);
|
||||
|
||||
/**
|
||||
* \brief Retrieves a vertex input pipeline library
|
||||
*
|
||||
@ -294,9 +304,6 @@ namespace dxvk {
|
||||
DxvkBindingLayoutObjects* createPipelineLayout(
|
||||
const DxvkBindingLayout& layout);
|
||||
|
||||
DxvkShaderPipelineLibrary* createPipelineLibrary(
|
||||
const DxvkShaderPipelineLibraryKey& key);
|
||||
|
||||
DxvkShaderPipelineLibrary* createPipelineLibraryLocked(
|
||||
const DxvkShaderPipelineLibraryKey& key);
|
||||
|
||||
|
@ -12,6 +12,16 @@ namespace dxvk {
|
||||
* \brief Packed entry header
|
||||
*/
|
||||
struct DxvkStateCacheEntryHeader {
|
||||
uint32_t entryType : 1;
|
||||
uint32_t stageMask : 5;
|
||||
uint32_t entrySize : 26;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Version 8 entry header
|
||||
*/
|
||||
struct DxvkStateCacheEntryHeaderV8 {
|
||||
uint32_t stageMask : 8;
|
||||
uint32_t entrySize : 24;
|
||||
};
|
||||
@ -44,6 +54,28 @@ namespace dxvk {
|
||||
return read(data);
|
||||
}
|
||||
|
||||
bool read(DxvkStateCacheKey& shaders, uint32_t version, VkShaderStageFlags stageFlags) {
|
||||
DxvkShaderKey dummyKey;
|
||||
|
||||
std::array<std::pair<VkShaderStageFlagBits, DxvkShaderKey*>, 6> stages = {{
|
||||
{ VK_SHADER_STAGE_VERTEX_BIT, &shaders.vs },
|
||||
{ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, &shaders.tcs },
|
||||
{ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &shaders.tes },
|
||||
{ VK_SHADER_STAGE_GEOMETRY_BIT, &shaders.gs },
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT, &shaders.fs },
|
||||
{ VK_SHADER_STAGE_COMPUTE_BIT, &dummyKey },
|
||||
}};
|
||||
|
||||
for (uint32_t i = 0; i < stages.size(); i++) {
|
||||
if (stageFlags & stages[i].first) {
|
||||
if (!read(*stages[i].second, version))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(DxvkBindingMaskV10& data, uint32_t version) {
|
||||
// v11 removes this field
|
||||
if (version >= 11)
|
||||
@ -208,8 +240,7 @@ namespace dxvk {
|
||||
&& this->tcs.eq(key.tcs)
|
||||
&& this->tes.eq(key.tes)
|
||||
&& this->gs.eq(key.gs)
|
||||
&& this->fs.eq(key.fs)
|
||||
&& this->cs.eq(key.cs);
|
||||
&& this->fs.eq(key.fs);
|
||||
}
|
||||
|
||||
|
||||
@ -220,7 +251,6 @@ namespace dxvk {
|
||||
hash.add(this->tes.hash());
|
||||
hash.add(this->gs.hash());
|
||||
hash.add(this->fs.hash());
|
||||
hash.add(this->cs.hash());
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -257,6 +287,31 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkStateCache::addPipelineLibrary(
|
||||
const DxvkStateCacheKey& shaders) {
|
||||
if (!m_enable || shaders.vs.eq(g_nullShaderKey))
|
||||
return;
|
||||
|
||||
// Do not add an entry that is already in the cache
|
||||
auto entries = m_entryMap.equal_range(shaders);
|
||||
|
||||
for (auto e = entries.first; e != entries.second; e++) {
|
||||
if (m_entries[e->second].type == DxvkStateCacheEntryType::PipelineLibrary)
|
||||
return;
|
||||
}
|
||||
|
||||
// Queue a job to write this pipeline to the cache
|
||||
std::unique_lock<dxvk::mutex> lock(m_writerLock);
|
||||
|
||||
m_writerQueue.push({
|
||||
DxvkStateCacheEntryType::PipelineLibrary, shaders,
|
||||
DxvkGraphicsPipelineStateInfo(), g_nullHash });
|
||||
m_writerCond.notify_one();
|
||||
|
||||
createWriter();
|
||||
}
|
||||
|
||||
|
||||
void DxvkStateCache::addGraphicsPipeline(
|
||||
const DxvkStateCacheKey& shaders,
|
||||
const DxvkGraphicsPipelineStateInfo& state) {
|
||||
@ -267,42 +322,17 @@ namespace dxvk {
|
||||
auto entries = m_entryMap.equal_range(shaders);
|
||||
|
||||
for (auto e = entries.first; e != entries.second; e++) {
|
||||
const DxvkStateCacheEntry& entry = m_entries[e->second];
|
||||
|
||||
if (entry.gpState == state)
|
||||
if (m_entries[e->second].type == DxvkStateCacheEntryType::MonolithicPipeline
|
||||
&& m_entries[e->second].gpState == state)
|
||||
return;
|
||||
}
|
||||
|
||||
// Queue a job to write this pipeline to the cache
|
||||
std::unique_lock<dxvk::mutex> lock(m_writerLock);
|
||||
|
||||
m_writerQueue.push({ shaders, state,
|
||||
DxvkComputePipelineStateInfo(), g_nullHash });
|
||||
m_writerCond.notify_one();
|
||||
|
||||
createWriter();
|
||||
}
|
||||
|
||||
|
||||
void DxvkStateCache::addComputePipeline(
|
||||
const DxvkStateCacheKey& shaders,
|
||||
const DxvkComputePipelineStateInfo& state) {
|
||||
if (!m_enable || shaders.cs.eq(g_nullShaderKey))
|
||||
return;
|
||||
|
||||
// Do not add an entry that is already in the cache
|
||||
auto entries = m_entryMap.equal_range(shaders);
|
||||
|
||||
for (auto e = entries.first; e != entries.second; e++) {
|
||||
if (m_entries[e->second].cpState == state)
|
||||
return;
|
||||
}
|
||||
|
||||
// Queue a job to write this pipeline to the cache
|
||||
std::unique_lock<dxvk::mutex> lock(m_writerLock);
|
||||
|
||||
m_writerQueue.push({ shaders,
|
||||
DxvkGraphicsPipelineStateInfo(), state, g_nullHash });
|
||||
m_writerQueue.push({
|
||||
DxvkStateCacheEntryType::MonolithicPipeline,
|
||||
shaders, state, g_nullHash });
|
||||
m_writerCond.notify_one();
|
||||
|
||||
createWriter();
|
||||
@ -334,8 +364,7 @@ namespace dxvk {
|
||||
|| !getShaderByKey(p->second.tcs, item.gp.tcs)
|
||||
|| !getShaderByKey(p->second.tes, item.gp.tes)
|
||||
|| !getShaderByKey(p->second.gs, item.gp.gs)
|
||||
|| !getShaderByKey(p->second.fs, item.gp.fs)
|
||||
|| !getShaderByKey(p->second.cs, item.cp.cs))
|
||||
|| !getShaderByKey(p->second.fs, item.gp.fs))
|
||||
continue;
|
||||
|
||||
if (!workerLock)
|
||||
@ -412,23 +441,35 @@ namespace dxvk {
|
||||
key.tes = getShaderKey(item.gp.tes);
|
||||
key.gs = getShaderKey(item.gp.gs);
|
||||
key.fs = getShaderKey(item.gp.fs);
|
||||
key.cs = getShaderKey(item.cp.cs);
|
||||
|
||||
if (item.cp.cs == nullptr) {
|
||||
auto pipeline = m_pipeManager->createGraphicsPipeline(item.gp);
|
||||
DxvkGraphicsPipeline* pipeline = nullptr;
|
||||
auto entries = m_entryMap.equal_range(key);
|
||||
|
||||
for (auto e = entries.first; e != entries.second; e++) {
|
||||
const auto& entry = m_entries[e->second];
|
||||
|
||||
switch (entry.type) {
|
||||
case DxvkStateCacheEntryType::MonolithicPipeline: {
|
||||
if (!pipeline)
|
||||
pipeline = m_pipeManager->createGraphicsPipeline(item.gp);
|
||||
|
||||
m_pipeWorkers->compileGraphicsPipeline(pipeline, entry.gpState);
|
||||
}
|
||||
} else {
|
||||
auto pipeline = m_pipeManager->createComputePipeline(item.cp);
|
||||
auto entries = m_entryMap.equal_range(key);
|
||||
} break;
|
||||
|
||||
for (auto e = entries.first; e != entries.second; e++) {
|
||||
const auto& entry = m_entries[e->second];
|
||||
m_pipeWorkers->compileComputePipeline(pipeline, entry.cpState);
|
||||
case DxvkStateCacheEntryType::PipelineLibrary: {
|
||||
if (!m_device->canUseGraphicsPipelineLibrary() || item.gp.vs == nullptr)
|
||||
break;
|
||||
|
||||
DxvkShaderPipelineLibraryKey libraryKey;
|
||||
libraryKey.addShader(item.gp.vs);
|
||||
|
||||
if (item.gp.tcs != nullptr) libraryKey.addShader(item.gp.tcs);
|
||||
if (item.gp.tes != nullptr) libraryKey.addShader(item.gp.tes);
|
||||
if (item.gp.gs != nullptr) libraryKey.addShader(item.gp.gs);
|
||||
|
||||
auto pipelineLibrary = m_pipeManager->createShaderPipelineLibrary(libraryKey);
|
||||
m_pipeWorkers->compilePipelineLibrary(pipelineLibrary, DxvkPipelinePriority::Normal);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -483,7 +524,6 @@ namespace dxvk {
|
||||
mapShaderToPipeline(entry.shaders.tes, entry.shaders);
|
||||
mapShaderToPipeline(entry.shaders.gs, entry.shaders);
|
||||
mapShaderToPipeline(entry.shaders.fs, entry.shaders);
|
||||
mapShaderToPipeline(entry.shaders.cs, entry.shaders);
|
||||
} else if (ifile) {
|
||||
numInvalidEntries += 1;
|
||||
}
|
||||
@ -531,11 +571,28 @@ namespace dxvk {
|
||||
DxvkStateCacheEntry& entry) const {
|
||||
// Read entry metadata and actual data
|
||||
DxvkStateCacheEntryHeader header;
|
||||
DxvkStateCacheEntryHeaderV8 headerV8;
|
||||
DxvkStateCacheEntryData data;
|
||||
VkShaderStageFlags stageMask;
|
||||
Sha1Hash hash;
|
||||
|
||||
if (!stream.read(reinterpret_cast<char*>(&header), sizeof(header))
|
||||
|| !stream.read(reinterpret_cast<char*>(&hash), sizeof(hash))
|
||||
if (version >= 16) {
|
||||
if (!stream.read(reinterpret_cast<char*>(&header), sizeof(header)))
|
||||
return false;
|
||||
|
||||
stageMask = VkShaderStageFlags(header.stageMask);
|
||||
} else {
|
||||
if (!stream.read(reinterpret_cast<char*>(&headerV8), sizeof(headerV8)))
|
||||
return false;
|
||||
|
||||
header.entryType = uint32_t(DxvkStateCacheEntryType::MonolithicPipeline);
|
||||
header.stageMask = headerV8.stageMask & VK_SHADER_STAGE_ALL_GRAPHICS;
|
||||
header.entrySize = headerV8.entrySize;
|
||||
|
||||
stageMask = VkShaderStageFlags(headerV8.stageMask);
|
||||
}
|
||||
|
||||
if (!stream.read(reinterpret_cast<char*>(&hash), sizeof(hash))
|
||||
|| !data.readFromStream(stream, header.entrySize))
|
||||
return false;
|
||||
|
||||
@ -543,16 +600,15 @@ namespace dxvk {
|
||||
if (hash != data.computeHash())
|
||||
return false;
|
||||
|
||||
// Read shader hashes
|
||||
VkShaderStageFlags stageMask = VkShaderStageFlags(header.stageMask);
|
||||
auto keys = &entry.shaders.vs;
|
||||
// Set up entry metadata
|
||||
entry.type = DxvkStateCacheEntryType(header.entryType);
|
||||
|
||||
for (uint32_t i = 0; i < 6; i++) {
|
||||
if (stageMask & VkShaderStageFlagBits(1 << i))
|
||||
data.read(keys[i], version);
|
||||
else
|
||||
keys[i] = g_nullShaderKey;
|
||||
}
|
||||
// Read shader hashes
|
||||
auto entryType = DxvkStateCacheEntryType(header.entryType);
|
||||
data.read(entry.shaders, version, stageMask);
|
||||
|
||||
if (entryType == DxvkStateCacheEntryType::PipelineLibrary)
|
||||
return true;
|
||||
|
||||
DxvkBindingMaskV10 dummyBindingMask = { };
|
||||
|
||||
@ -610,10 +666,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
// Read non-zero spec constants
|
||||
auto& sc = (stageMask & VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
? entry.cpState.sc
|
||||
: entry.gpState.sc;
|
||||
|
||||
uint32_t specConstantMask = 0;
|
||||
|
||||
if (!data.read(specConstantMask, version))
|
||||
@ -621,11 +673,15 @@ namespace dxvk {
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumSpecConstants; i++) {
|
||||
if (specConstantMask & (1 << i)) {
|
||||
if (!data.read(sc.specConstants[i], version))
|
||||
if (!data.read(entry.gpState.sc.specConstants[i], version))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute shaders are no longer supported
|
||||
if (stageMask & VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -646,7 +702,7 @@ namespace dxvk {
|
||||
}
|
||||
}
|
||||
|
||||
if (!(stageMask & VK_SHADER_STAGE_COMPUTE_BIT)) {
|
||||
if (entry.type != DxvkStateCacheEntryType::PipelineLibrary) {
|
||||
// Write out common pipeline state
|
||||
data.write(entry.gpState.ia);
|
||||
data.write(entry.gpState.il);
|
||||
@ -671,28 +727,25 @@ namespace dxvk {
|
||||
|
||||
for (uint32_t i = 0; i < entry.gpState.il.bindingCount(); i++)
|
||||
data.write(entry.gpState.ilBindings[i]);
|
||||
}
|
||||
|
||||
// Write out all non-zero spec constants
|
||||
auto& sc = (stageMask & VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
? entry.cpState.sc
|
||||
: entry.gpState.sc;
|
||||
|
||||
uint32_t specConstantMask = 0;
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumSpecConstants; i++)
|
||||
specConstantMask |= sc.specConstants[i] ? (1 << i) : 0;
|
||||
specConstantMask |= entry.gpState.sc.specConstants[i] ? (1 << i) : 0;
|
||||
|
||||
data.write(specConstantMask);
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumSpecConstants; i++) {
|
||||
if (specConstantMask & (1 << i))
|
||||
data.write(sc.specConstants[i]);
|
||||
data.write(entry.gpState.sc.specConstants[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// General layout: header -> hash -> data
|
||||
DxvkStateCacheEntryHeader header;
|
||||
header.stageMask = uint8_t(stageMask);
|
||||
header.entryType = uint32_t(entry.type);
|
||||
header.stageMask = uint32_t(stageMask);
|
||||
header.entrySize = data.size();
|
||||
|
||||
Sha1Hash hash = data.computeHash();
|
||||
|
@ -37,30 +37,27 @@ namespace dxvk {
|
||||
~DxvkStateCache();
|
||||
|
||||
/**
|
||||
* Adds a graphics pipeline to the cache
|
||||
* \brief Adds pipeline library 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
|
||||
*/
|
||||
void addPipelineLibrary(
|
||||
const DxvkStateCacheKey& shaders);
|
||||
|
||||
/**
|
||||
* \brief 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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@ -83,7 +80,6 @@ namespace dxvk {
|
||||
|
||||
struct WorkerItem {
|
||||
DxvkGraphicsPipelineShaders gp;
|
||||
DxvkComputePipelineShaders cp;
|
||||
};
|
||||
|
||||
DxvkDevice* m_device;
|
||||
|
@ -19,7 +19,6 @@ namespace dxvk {
|
||||
DxvkShaderKey tes;
|
||||
DxvkShaderKey gs;
|
||||
DxvkShaderKey fs;
|
||||
DxvkShaderKey cs;
|
||||
|
||||
bool eq(const DxvkStateCacheKey& key) const;
|
||||
|
||||
@ -27,6 +26,15 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief State entry type
|
||||
*/
|
||||
enum class DxvkStateCacheEntryType : uint32_t {
|
||||
MonolithicPipeline = 0,
|
||||
PipelineLibrary = 1,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief State entry
|
||||
*
|
||||
@ -36,9 +44,9 @@ namespace dxvk {
|
||||
* that is used as a check sum to verify integrity.
|
||||
*/
|
||||
struct DxvkStateCacheEntry {
|
||||
DxvkStateCacheEntryType type;
|
||||
DxvkStateCacheKey shaders;
|
||||
DxvkGraphicsPipelineStateInfo gpState;
|
||||
DxvkComputePipelineStateInfo cpState;
|
||||
Sha1Hash hash;
|
||||
};
|
||||
|
||||
@ -52,7 +60,7 @@ namespace dxvk {
|
||||
*/
|
||||
struct DxvkStateCacheHeader {
|
||||
char magic[4] = { 'D', 'X', 'V', 'K' };
|
||||
uint32_t version = 15;
|
||||
uint32_t version = 16;
|
||||
uint32_t entrySize = 0; /* no longer meaningful */
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user