mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +01:00
[dxvk] Bump state cache version to v5
This commit is contained in:
parent
37f1087783
commit
584fd870b2
@ -7,6 +7,20 @@ namespace dxvk {
|
|||||||
static const Sha1Hash g_nullHash = Sha1Hash::compute(nullptr, 0);
|
static const Sha1Hash g_nullHash = Sha1Hash::compute(nullptr, 0);
|
||||||
static const DxvkShaderKey g_nullShaderKey = DxvkShaderKey();
|
static const DxvkShaderKey g_nullShaderKey = DxvkShaderKey();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool readCacheEntryTyped(std::istream& stream, T& entry) {
|
||||||
|
auto data = reinterpret_cast<char*>(&entry);
|
||||||
|
auto size = sizeof(entry);
|
||||||
|
|
||||||
|
if (!stream.read(data, size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Sha1Hash expectedHash = std::exchange(entry.hash, g_nullHash);
|
||||||
|
Sha1Hash computedHash = Sha1Hash::compute(entry);
|
||||||
|
return expectedHash == computedHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DxvkStateCacheKey::eq(const DxvkStateCacheKey& key) const {
|
bool DxvkStateCacheKey::eq(const DxvkStateCacheKey& key) const {
|
||||||
return this->vs.eq(key.vs)
|
return this->vs.eq(key.vs)
|
||||||
&& this->tcs.eq(key.tcs)
|
&& this->tcs.eq(key.tcs)
|
||||||
@ -282,8 +296,13 @@ namespace dxvk {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Struct size hasn't changed between v2/v3
|
// Struct size hasn't changed between v2 and v4
|
||||||
if (curHeader.entrySize != newHeader.entrySize) {
|
size_t expectedSize = newHeader.entrySize;
|
||||||
|
|
||||||
|
if (curHeader.version <= 4)
|
||||||
|
expectedSize = sizeof(DxvkStateCacheEntryV4);
|
||||||
|
|
||||||
|
if (curHeader.entrySize != expectedSize) {
|
||||||
Logger::warn("DXVK: State cache entry size changed");
|
Logger::warn("DXVK: State cache entry size changed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -306,11 +325,7 @@ namespace dxvk {
|
|||||||
while (ifile) {
|
while (ifile) {
|
||||||
DxvkStateCacheEntry entry;
|
DxvkStateCacheEntry entry;
|
||||||
|
|
||||||
if (readCacheEntry(ifile, entry)) {
|
if (readCacheEntry(curHeader.version, ifile, entry)) {
|
||||||
switch (curHeader.version) {
|
|
||||||
case 2: convertEntryV2(entry); /* fall through */
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t entryId = m_entries.size();
|
size_t entryId = m_entries.size();
|
||||||
m_entries.push_back(entry);
|
m_entries.push_back(entry);
|
||||||
|
|
||||||
@ -364,17 +379,22 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
bool DxvkStateCache::readCacheEntry(
|
bool DxvkStateCache::readCacheEntry(
|
||||||
|
uint32_t version,
|
||||||
std::istream& stream,
|
std::istream& stream,
|
||||||
DxvkStateCacheEntry& entry) const {
|
DxvkStateCacheEntry& entry) const {
|
||||||
auto data = reinterpret_cast<char*>(&entry);
|
if (version <= 4) {
|
||||||
auto size = sizeof(DxvkStateCacheEntry);
|
DxvkStateCacheEntryV4 v4;
|
||||||
|
|
||||||
if (!stream.read(data, size))
|
if (!readCacheEntryTyped(stream, v4))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Sha1Hash expectedHash = std::exchange(entry.hash, g_nullHash);
|
if (version == 2)
|
||||||
Sha1Hash computedHash = Sha1Hash::compute(entry);
|
convertEntryV2(v4);
|
||||||
return expectedHash == computedHash;
|
|
||||||
|
return convertEntryV4(v4, entry);
|
||||||
|
} else {
|
||||||
|
return readCacheEntryTyped(stream, entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -392,7 +412,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
bool DxvkStateCache::convertEntryV2(
|
bool DxvkStateCache::convertEntryV2(
|
||||||
DxvkStateCacheEntry& entry) const {
|
DxvkStateCacheEntryV4& entry) const {
|
||||||
// Semantics changed:
|
// Semantics changed:
|
||||||
// v2: rsDepthClampEnable
|
// v2: rsDepthClampEnable
|
||||||
// v3: rsDepthClipEnable
|
// v3: rsDepthClipEnable
|
||||||
@ -405,6 +425,62 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkStateCache::convertEntryV4(
|
||||||
|
const DxvkStateCacheEntryV4& in,
|
||||||
|
DxvkStateCacheEntry& out) const {
|
||||||
|
out.shaders = in.shaders;
|
||||||
|
out.cpState = in.cpState;
|
||||||
|
out.format = in.format;
|
||||||
|
out.hash = in.hash;
|
||||||
|
|
||||||
|
out.gpState.bsBindingMask = in.gpState.bsBindingMask;
|
||||||
|
|
||||||
|
out.gpState.iaPrimitiveTopology = in.gpState.iaPrimitiveTopology;
|
||||||
|
out.gpState.iaPrimitiveRestart = in.gpState.iaPrimitiveRestart;
|
||||||
|
out.gpState.iaPatchVertexCount = in.gpState.iaPatchVertexCount;
|
||||||
|
|
||||||
|
out.gpState.ilAttributeCount = in.gpState.ilAttributeCount;
|
||||||
|
out.gpState.ilBindingCount = in.gpState.ilBindingCount;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < in.gpState.ilAttributeCount; i++)
|
||||||
|
out.gpState.ilAttributes[i] = in.gpState.ilAttributes[i];
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < in.gpState.ilBindingCount; i++) {
|
||||||
|
out.gpState.ilBindings[i] = in.gpState.ilBindings[i];
|
||||||
|
out.gpState.ilDivisors[i] = in.gpState.ilDivisors[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
out.gpState.rsDepthClipEnable = in.gpState.rsDepthClipEnable;
|
||||||
|
out.gpState.rsDepthBiasEnable = in.gpState.rsDepthBiasEnable;
|
||||||
|
out.gpState.rsPolygonMode = in.gpState.rsPolygonMode;
|
||||||
|
out.gpState.rsCullMode = in.gpState.rsCullMode;
|
||||||
|
out.gpState.rsFrontFace = in.gpState.rsFrontFace;
|
||||||
|
out.gpState.rsViewportCount = in.gpState.rsViewportCount;
|
||||||
|
out.gpState.rsSampleCount = in.gpState.rsSampleCount;
|
||||||
|
|
||||||
|
out.gpState.msSampleCount = in.gpState.msSampleCount;
|
||||||
|
out.gpState.msSampleMask = in.gpState.msSampleMask;
|
||||||
|
out.gpState.msEnableAlphaToCoverage = in.gpState.msEnableAlphaToCoverage;
|
||||||
|
|
||||||
|
out.gpState.dsEnableDepthTest = in.gpState.dsEnableDepthTest;
|
||||||
|
out.gpState.dsEnableDepthWrite = in.gpState.dsEnableDepthWrite;
|
||||||
|
out.gpState.dsEnableStencilTest = in.gpState.dsEnableStencilTest;
|
||||||
|
out.gpState.dsDepthCompareOp = in.gpState.dsDepthCompareOp;
|
||||||
|
out.gpState.dsStencilOpFront = in.gpState.dsStencilOpFront;
|
||||||
|
out.gpState.dsStencilOpBack = in.gpState.dsStencilOpBack;
|
||||||
|
|
||||||
|
out.gpState.omEnableLogicOp = in.gpState.omEnableLogicOp;
|
||||||
|
out.gpState.omLogicOp = in.gpState.omLogicOp;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||||
|
out.gpState.omBlendAttachments[i] = in.gpState.omBlendAttachments[i];
|
||||||
|
out.gpState.omComponentMapping[i] = in.gpState.omComponentMapping[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkStateCache::workerFunc() {
|
void DxvkStateCache::workerFunc() {
|
||||||
env::setThreadName("dxvk-shader");
|
env::setThreadName("dxvk-shader");
|
||||||
|
|
||||||
|
@ -8,67 +8,12 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "dxvk_pipemanager.h"
|
#include "dxvk_state_cache_types.h"
|
||||||
#include "dxvk_renderpass.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
class DxvkDevice;
|
class DxvkDevice;
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief State cache entry key
|
|
||||||
*
|
|
||||||
* Stores the shader keys for all
|
|
||||||
* graphics shader stages. Used to
|
|
||||||
* look up cached state entries.
|
|
||||||
*/
|
|
||||||
struct DxvkStateCacheKey {
|
|
||||||
DxvkShaderKey vs;
|
|
||||||
DxvkShaderKey tcs;
|
|
||||||
DxvkShaderKey tes;
|
|
||||||
DxvkShaderKey gs;
|
|
||||||
DxvkShaderKey fs;
|
|
||||||
DxvkShaderKey cs;
|
|
||||||
|
|
||||||
bool eq(const DxvkStateCacheKey& key) const;
|
|
||||||
|
|
||||||
size_t hash() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief State entry
|
|
||||||
*
|
|
||||||
* Stores the shaders used in a pipeline, as well
|
|
||||||
* as the full state vector, including its render
|
|
||||||
* pass format. This also includes a SHA-1 hash
|
|
||||||
* that is used as a check sum to verify integrity.
|
|
||||||
*/
|
|
||||||
struct DxvkStateCacheEntry {
|
|
||||||
DxvkStateCacheKey shaders;
|
|
||||||
DxvkGraphicsPipelineStateInfo gpState;
|
|
||||||
DxvkComputePipelineStateInfo cpState;
|
|
||||||
DxvkRenderPassFormat format;
|
|
||||||
Sha1Hash hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief State cache header
|
|
||||||
*
|
|
||||||
* Stores the state cache format version. If an
|
|
||||||
* existing cache file is incompatible to the
|
|
||||||
* current version, it will be discarded.
|
|
||||||
*/
|
|
||||||
struct DxvkStateCacheHeader {
|
|
||||||
char magic[4] = { 'D', 'X', 'V', 'K' };
|
|
||||||
uint32_t version = 4;
|
|
||||||
uint32_t entrySize = sizeof(DxvkStateCacheEntry);
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(DxvkStateCacheHeader) == 12);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief State cache
|
* \brief State cache
|
||||||
*
|
*
|
||||||
@ -203,6 +148,7 @@ namespace dxvk {
|
|||||||
DxvkStateCacheHeader& header) const;
|
DxvkStateCacheHeader& header) const;
|
||||||
|
|
||||||
bool readCacheEntry(
|
bool readCacheEntry(
|
||||||
|
uint32_t version,
|
||||||
std::istream& stream,
|
std::istream& stream,
|
||||||
DxvkStateCacheEntry& entry) const;
|
DxvkStateCacheEntry& entry) const;
|
||||||
|
|
||||||
@ -211,7 +157,11 @@ namespace dxvk {
|
|||||||
DxvkStateCacheEntry& entry) const;
|
DxvkStateCacheEntry& entry) const;
|
||||||
|
|
||||||
bool convertEntryV2(
|
bool convertEntryV2(
|
||||||
DxvkStateCacheEntry& entry) const;
|
DxvkStateCacheEntryV4& entry) const;
|
||||||
|
|
||||||
|
bool convertEntryV4(
|
||||||
|
const DxvkStateCacheEntryV4& in,
|
||||||
|
DxvkStateCacheEntry& out) const;
|
||||||
|
|
||||||
void workerFunc();
|
void workerFunc();
|
||||||
|
|
||||||
|
117
src/dxvk/dxvk_state_cache_types.h
Normal file
117
src/dxvk/dxvk_state_cache_types.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dxvk_pipemanager.h"
|
||||||
|
#include "dxvk_renderpass.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief State cache entry key
|
||||||
|
*
|
||||||
|
* Stores the shader keys for all
|
||||||
|
* graphics shader stages. Used to
|
||||||
|
* look up cached state entries.
|
||||||
|
*/
|
||||||
|
struct DxvkStateCacheKey {
|
||||||
|
DxvkShaderKey vs;
|
||||||
|
DxvkShaderKey tcs;
|
||||||
|
DxvkShaderKey tes;
|
||||||
|
DxvkShaderKey gs;
|
||||||
|
DxvkShaderKey fs;
|
||||||
|
DxvkShaderKey cs;
|
||||||
|
|
||||||
|
bool eq(const DxvkStateCacheKey& key) const;
|
||||||
|
|
||||||
|
size_t hash() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief State entry
|
||||||
|
*
|
||||||
|
* Stores the shaders used in a pipeline, as well
|
||||||
|
* as the full state vector, including its render
|
||||||
|
* pass format. This also includes a SHA-1 hash
|
||||||
|
* that is used as a check sum to verify integrity.
|
||||||
|
*/
|
||||||
|
struct DxvkStateCacheEntry {
|
||||||
|
DxvkStateCacheKey shaders;
|
||||||
|
DxvkGraphicsPipelineStateInfo gpState;
|
||||||
|
DxvkComputePipelineStateInfo cpState;
|
||||||
|
DxvkRenderPassFormat format;
|
||||||
|
Sha1Hash hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief State cache header
|
||||||
|
*
|
||||||
|
* Stores the state cache format version. If an
|
||||||
|
* existing cache file is incompatible to the
|
||||||
|
* current version, it will be discarded.
|
||||||
|
*/
|
||||||
|
struct DxvkStateCacheHeader {
|
||||||
|
char magic[4] = { 'D', 'X', 'V', 'K' };
|
||||||
|
uint32_t version = 5;
|
||||||
|
uint32_t entrySize = sizeof(DxvkStateCacheEntry);
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(DxvkStateCacheHeader) == 12);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Version 4 graphics pipeline state
|
||||||
|
*/
|
||||||
|
struct DxvkGraphicsPipelineStateInfoV4 {
|
||||||
|
DxvkBindingMask bsBindingMask;
|
||||||
|
|
||||||
|
VkPrimitiveTopology iaPrimitiveTopology;
|
||||||
|
VkBool32 iaPrimitiveRestart;
|
||||||
|
uint32_t iaPatchVertexCount;
|
||||||
|
|
||||||
|
uint32_t ilAttributeCount;
|
||||||
|
uint32_t ilBindingCount;
|
||||||
|
VkVertexInputAttributeDescription ilAttributes[DxvkLimits::MaxNumVertexAttributes];
|
||||||
|
VkVertexInputBindingDescription ilBindings[DxvkLimits::MaxNumVertexBindings];
|
||||||
|
uint32_t ilDivisors[DxvkLimits::MaxNumVertexBindings];
|
||||||
|
|
||||||
|
VkBool32 rsDepthClipEnable;
|
||||||
|
VkBool32 rsDepthBiasEnable;
|
||||||
|
VkPolygonMode rsPolygonMode;
|
||||||
|
VkCullModeFlags rsCullMode;
|
||||||
|
VkFrontFace rsFrontFace;
|
||||||
|
uint32_t rsViewportCount;
|
||||||
|
VkSampleCountFlags rsSampleCount;
|
||||||
|
|
||||||
|
VkSampleCountFlags msSampleCount;
|
||||||
|
uint32_t msSampleMask;
|
||||||
|
VkBool32 msEnableAlphaToCoverage;
|
||||||
|
|
||||||
|
VkCompareOp xsAlphaCompareOp;
|
||||||
|
|
||||||
|
VkBool32 dsEnableDepthTest;
|
||||||
|
VkBool32 dsEnableDepthWrite;
|
||||||
|
VkBool32 dsEnableStencilTest;
|
||||||
|
VkCompareOp dsDepthCompareOp;
|
||||||
|
VkStencilOpState dsStencilOpFront;
|
||||||
|
VkStencilOpState dsStencilOpBack;
|
||||||
|
|
||||||
|
VkBool32 omEnableLogicOp;
|
||||||
|
VkLogicOp omLogicOp;
|
||||||
|
VkPipelineColorBlendAttachmentState omBlendAttachments[MaxNumRenderTargets];
|
||||||
|
VkComponentMapping omComponentMapping[MaxNumRenderTargets];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Version 4 state cache entry
|
||||||
|
*/
|
||||||
|
struct DxvkStateCacheEntryV4 {
|
||||||
|
DxvkStateCacheKey shaders;
|
||||||
|
DxvkGraphicsPipelineStateInfoV4 gpState;
|
||||||
|
DxvkComputePipelineStateInfo cpState;
|
||||||
|
DxvkRenderPassFormat format;
|
||||||
|
Sha1Hash hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user