mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-21 21:57:39 +01:00
[dxvk] Bump state cache version to v12
And remove its reliance on the old render pass format struct.
This commit is contained in:
parent
39a2b1cb7a
commit
e3a63d4faa
@ -51,7 +51,7 @@ namespace dxvk {
|
||||
VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass) {
|
||||
DxvkGraphicsPipelineInstance* instance = this->findInstance(state, renderPass);
|
||||
DxvkGraphicsPipelineInstance* instance = this->findInstance(state);
|
||||
|
||||
if (unlikely(!instance)) {
|
||||
// Exit early if the state vector is invalid
|
||||
@ -60,13 +60,13 @@ namespace dxvk {
|
||||
|
||||
// Prevent other threads from adding new instances and check again
|
||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||
instance = this->findInstance(state, renderPass);
|
||||
instance = this->findInstance(state);
|
||||
|
||||
if (!instance) {
|
||||
// Keep pipeline object locked, at worst we're going to stall
|
||||
// a state cache worker and the current thread needs priority.
|
||||
instance = this->createInstance(state, renderPass);
|
||||
this->writePipelineStateToCache(state, renderPass->format());
|
||||
instance = this->createInstance(state);
|
||||
this->writePipelineStateToCache(state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,8 +75,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxvkGraphicsPipeline::compilePipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass) {
|
||||
const DxvkGraphicsPipelineStateInfo& state) {
|
||||
// Exit early if the state vector is invalid
|
||||
if (!this->validatePipelineState(state, false))
|
||||
return;
|
||||
@ -85,26 +84,24 @@ namespace dxvk {
|
||||
// similar pipelines concurrently is fragile on some drivers
|
||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||
|
||||
if (!this->findInstance(state, renderPass))
|
||||
this->createInstance(state, renderPass);
|
||||
if (!this->findInstance(state))
|
||||
this->createInstance(state);
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::createInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass) {
|
||||
VkPipeline pipeline = this->createPipeline(state, renderPass);
|
||||
const DxvkGraphicsPipelineStateInfo& state) {
|
||||
VkPipeline pipeline = this->createPipeline(state);
|
||||
|
||||
m_pipeMgr->m_numGraphicsPipelines += 1;
|
||||
return &(*m_pipelines.emplace(state, renderPass, pipeline));
|
||||
return &(*m_pipelines.emplace(state, pipeline));
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass) {
|
||||
const DxvkGraphicsPipelineStateInfo& state) {
|
||||
for (auto& instance : m_pipelines) {
|
||||
if (instance.isCompatible(state, renderPass))
|
||||
if (instance.isCompatible(state))
|
||||
return &instance;
|
||||
}
|
||||
|
||||
@ -113,8 +110,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
VkPipeline DxvkGraphicsPipeline::createPipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass) const {
|
||||
const DxvkGraphicsPipelineStateInfo& state) const {
|
||||
if (Logger::logLevel() <= LogLevel::Debug) {
|
||||
Logger::debug("Compiling graphics pipeline...");
|
||||
this->logPipelineState(LogLevel::Debug, state);
|
||||
@ -551,8 +547,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxvkGraphicsPipeline::writePipelineStateToCache(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPassFormat& format) const {
|
||||
const DxvkGraphicsPipelineStateInfo& state) const {
|
||||
if (m_pipeMgr->m_stateCache == nullptr)
|
||||
return;
|
||||
|
||||
@ -563,7 +558,7 @@ namespace dxvk {
|
||||
if (m_shaders.gs != nullptr) key.gs = m_shaders.gs->getShaderKey();
|
||||
if (m_shaders.fs != nullptr) key.fs = m_shaders.fs->getShaderKey();
|
||||
|
||||
m_pipeMgr->m_stateCache->addGraphicsPipeline(key, state, format);
|
||||
m_pipeMgr->m_stateCache->addGraphicsPipeline(key, state);
|
||||
}
|
||||
|
||||
|
||||
|
@ -94,15 +94,12 @@ namespace dxvk {
|
||||
|
||||
DxvkGraphicsPipelineInstance()
|
||||
: m_stateVector (),
|
||||
m_renderPass (nullptr),
|
||||
m_pipeline (VK_NULL_HANDLE) { }
|
||||
|
||||
DxvkGraphicsPipelineInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* rp,
|
||||
VkPipeline pipe)
|
||||
: m_stateVector (state),
|
||||
m_renderPass (rp),
|
||||
m_pipeline (pipe) { }
|
||||
|
||||
/**
|
||||
@ -113,10 +110,8 @@ namespace dxvk {
|
||||
* \returns \c true if the specialization is compatible
|
||||
*/
|
||||
bool isCompatible(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* rp) {
|
||||
return m_renderPass == rp
|
||||
&& m_stateVector == state;
|
||||
const DxvkGraphicsPipelineStateInfo& state) {
|
||||
return m_stateVector == state;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,7 +125,6 @@ namespace dxvk {
|
||||
private:
|
||||
|
||||
DxvkGraphicsPipelineStateInfo m_stateVector;
|
||||
const DxvkRenderPass* m_renderPass;
|
||||
VkPipeline m_pipeline;
|
||||
|
||||
};
|
||||
@ -212,11 +206,9 @@ namespace dxvk {
|
||||
* Asynchronously compiles the given pipeline
|
||||
* and stores the result for future use.
|
||||
* \param [in] state Pipeline state vector
|
||||
* \param [in] renderPass The render pass
|
||||
*/
|
||||
void compilePipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass);
|
||||
const DxvkGraphicsPipelineStateInfo& state);
|
||||
|
||||
private:
|
||||
|
||||
@ -238,16 +230,13 @@ namespace dxvk {
|
||||
sync::List<DxvkGraphicsPipelineInstance> m_pipelines;
|
||||
|
||||
DxvkGraphicsPipelineInstance* createInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass);
|
||||
const DxvkGraphicsPipelineStateInfo& state);
|
||||
|
||||
DxvkGraphicsPipelineInstance* findInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass);
|
||||
const DxvkGraphicsPipelineStateInfo& state);
|
||||
|
||||
VkPipeline createPipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass* renderPass) const;
|
||||
const DxvkGraphicsPipelineStateInfo& state) const;
|
||||
|
||||
void destroyPipeline(
|
||||
VkPipeline pipeline) const;
|
||||
@ -264,8 +253,7 @@ namespace dxvk {
|
||||
bool trusted) const;
|
||||
|
||||
void writePipelineStateToCache(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPassFormat& format) const;
|
||||
const DxvkGraphicsPipelineStateInfo& state) const;
|
||||
|
||||
void logPipelineState(
|
||||
LogLevel level,
|
||||
|
@ -62,6 +62,14 @@ namespace dxvk {
|
||||
return read(data);
|
||||
}
|
||||
|
||||
bool read(DxvkRtInfo& data, uint32_t version) {
|
||||
// v12 introduced this field
|
||||
if (version < 12)
|
||||
return true;
|
||||
|
||||
return read(data);
|
||||
}
|
||||
|
||||
bool read(DxvkIlBinding& data, uint32_t version) {
|
||||
if (version < 10) {
|
||||
DxvkIlBindingV9 v9;
|
||||
@ -76,6 +84,34 @@ namespace dxvk {
|
||||
return read(data);
|
||||
}
|
||||
|
||||
|
||||
bool read(DxvkRenderPassFormatV11& data, uint32_t version) {
|
||||
uint8_t sampleCount = 0;
|
||||
uint8_t imageFormat = 0;
|
||||
uint8_t imageLayout = 0;
|
||||
|
||||
if (!read(sampleCount)
|
||||
|| !read(imageFormat)
|
||||
|| !read(imageLayout))
|
||||
return false;
|
||||
|
||||
data.sampleCount = VkSampleCountFlagBits(sampleCount);
|
||||
data.depth.format = VkFormat(imageFormat);
|
||||
data.depth.layout = unpackImageLayoutV11(imageLayout);
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
if (!read(imageFormat)
|
||||
|| !read(imageLayout))
|
||||
return false;
|
||||
|
||||
data.color[i].format = VkFormat(imageFormat);
|
||||
data.color[i].layout = unpackImageLayoutV11(imageLayout);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool write(const T& data) {
|
||||
if (m_size + sizeof(T) > MaxSize)
|
||||
@ -114,6 +150,15 @@ namespace dxvk {
|
||||
return true;
|
||||
}
|
||||
|
||||
static VkImageLayout unpackImageLayoutV11(
|
||||
uint8_t layout) {
|
||||
switch (layout) {
|
||||
case 0x80: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
case 0x81: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
|
||||
default: return VkImageLayout(layout);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -199,8 +244,7 @@ namespace dxvk {
|
||||
|
||||
void DxvkStateCache::addGraphicsPipeline(
|
||||
const DxvkStateCacheKey& shaders,
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPassFormat& format) {
|
||||
const DxvkGraphicsPipelineStateInfo& state) {
|
||||
if (shaders.vs.eq(g_nullShaderKey))
|
||||
return;
|
||||
|
||||
@ -210,7 +254,7 @@ namespace dxvk {
|
||||
for (auto e = entries.first; e != entries.second; e++) {
|
||||
const DxvkStateCacheEntry& entry = m_entries[e->second];
|
||||
|
||||
if (entry.format.eq(format) && entry.gpState == state)
|
||||
if (entry.gpState == state)
|
||||
return;
|
||||
}
|
||||
|
||||
@ -218,8 +262,7 @@ namespace dxvk {
|
||||
std::unique_lock<dxvk::mutex> lock(m_writerLock);
|
||||
|
||||
m_writerQueue.push({ shaders, state,
|
||||
DxvkComputePipelineStateInfo(),
|
||||
format, g_nullHash });
|
||||
DxvkComputePipelineStateInfo(), g_nullHash });
|
||||
m_writerCond.notify_one();
|
||||
|
||||
createWriter();
|
||||
@ -244,8 +287,7 @@ namespace dxvk {
|
||||
std::unique_lock<dxvk::mutex> lock(m_writerLock);
|
||||
|
||||
m_writerQueue.push({ shaders,
|
||||
DxvkGraphicsPipelineStateInfo(), state,
|
||||
DxvkRenderPassFormat(), g_nullHash });
|
||||
DxvkGraphicsPipelineStateInfo(), state, g_nullHash });
|
||||
m_writerCond.notify_one();
|
||||
|
||||
createWriter();
|
||||
@ -360,11 +402,7 @@ namespace dxvk {
|
||||
|
||||
for (auto e = entries.first; e != entries.second; e++) {
|
||||
const auto& entry = m_entries[e->second];
|
||||
|
||||
if (m_passManager->validateRenderPassFormat(entry.format)) {
|
||||
auto rp = m_passManager->getRenderPass(entry.format);
|
||||
pipeline->compilePipeline(entry.gpState, rp);
|
||||
}
|
||||
pipeline->compilePipeline(entry.gpState);
|
||||
}
|
||||
} else {
|
||||
auto pipeline = m_pipeManager->createComputePipeline(item.cp);
|
||||
@ -504,31 +542,12 @@ namespace dxvk {
|
||||
return false;
|
||||
} else {
|
||||
// Read packed render pass format
|
||||
uint8_t sampleCount = 0;
|
||||
uint8_t imageFormat = 0;
|
||||
uint8_t imageLayout = 0;
|
||||
|
||||
if (!data.read(sampleCount, version)
|
||||
|| !data.read(imageFormat, version)
|
||||
|| !data.read(imageLayout, version))
|
||||
return false;
|
||||
|
||||
entry.format.sampleCount = VkSampleCountFlagBits(sampleCount);
|
||||
entry.format.depth.format = VkFormat(imageFormat);
|
||||
entry.format.depth.layout = unpackImageLayout(imageLayout);
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
if (!data.read(imageFormat, version)
|
||||
|| !data.read(imageLayout, version))
|
||||
return false;
|
||||
|
||||
entry.format.color[i].format = VkFormat(imageFormat);
|
||||
entry.format.color[i].layout = unpackImageLayout(imageLayout);
|
||||
if (version < 12) {
|
||||
DxvkRenderPassFormatV11 v11;
|
||||
data.read(v11, version);
|
||||
entry.gpState.rt = v11.convert();
|
||||
}
|
||||
|
||||
if (!validateRenderPassFormat(entry.format))
|
||||
return false;
|
||||
|
||||
// Read common pipeline state
|
||||
if (!data.read(dummyBindingMask, version)
|
||||
|| !data.read(entry.gpState.ia, version)
|
||||
@ -537,6 +556,7 @@ namespace dxvk {
|
||||
|| !data.read(entry.gpState.ms, version)
|
||||
|| !data.read(entry.gpState.ds, version)
|
||||
|| !data.read(entry.gpState.om, version)
|
||||
|| !data.read(entry.gpState.rt, version)
|
||||
|| !data.read(entry.gpState.dsFront, version)
|
||||
|| !data.read(entry.gpState.dsBack, version))
|
||||
return false;
|
||||
@ -608,16 +628,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
if (!(stageMask & VK_SHADER_STAGE_COMPUTE_BIT)) {
|
||||
// Pack render pass format
|
||||
data.write(uint8_t(entry.format.sampleCount));
|
||||
data.write(uint8_t(entry.format.depth.format));
|
||||
data.write(packImageLayout(entry.format.depth.layout));
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
data.write(uint8_t(entry.format.color[i].format));
|
||||
data.write(packImageLayout(entry.format.color[i].layout));
|
||||
}
|
||||
|
||||
// Write out common pipeline state
|
||||
data.write(entry.gpState.ia);
|
||||
data.write(entry.gpState.il);
|
||||
@ -625,6 +635,7 @@ namespace dxvk {
|
||||
data.write(entry.gpState.ms);
|
||||
data.write(entry.gpState.ds);
|
||||
data.write(entry.gpState.om);
|
||||
data.write(entry.gpState.rt);
|
||||
data.write(entry.gpState.dsFront);
|
||||
data.write(entry.gpState.dsBack);
|
||||
|
||||
@ -785,47 +796,4 @@ namespace dxvk {
|
||||
return env::getEnvVar("DXVK_STATE_CACHE_PATH");
|
||||
}
|
||||
|
||||
|
||||
uint8_t DxvkStateCache::packImageLayout(
|
||||
VkImageLayout layout) {
|
||||
switch (layout) {
|
||||
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: return 0x80;
|
||||
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: return 0x81;
|
||||
default: return uint8_t(layout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VkImageLayout DxvkStateCache::unpackImageLayout(
|
||||
uint8_t layout) {
|
||||
switch (layout) {
|
||||
case 0x80: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
case 0x81: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
|
||||
default: return VkImageLayout(layout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DxvkStateCache::validateRenderPassFormat(
|
||||
const DxvkRenderPassFormat& format) {
|
||||
bool valid = true;
|
||||
|
||||
if (format.depth.format) {
|
||||
valid &= format.depth.layout == VK_IMAGE_LAYOUT_GENERAL
|
||||
|| format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
||||
|| format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
|
||||
|| format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
|
||||
|| format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets && valid; i++) {
|
||||
if (format.color[i].format) {
|
||||
valid &= format.color[i].layout == VK_IMAGE_LAYOUT_GENERAL
|
||||
|| format.color[i].layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,8 +45,7 @@ namespace dxvk {
|
||||
*/
|
||||
void addGraphicsPipeline(
|
||||
const DxvkStateCacheKey& shaders,
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPassFormat& format);
|
||||
const DxvkGraphicsPipelineStateInfo& state);
|
||||
|
||||
/**
|
||||
* Adds a compute pipeline to the cache
|
||||
@ -170,15 +169,6 @@ namespace dxvk {
|
||||
|
||||
std::string getCacheDir() const;
|
||||
|
||||
static uint8_t packImageLayout(
|
||||
VkImageLayout layout);
|
||||
|
||||
static VkImageLayout unpackImageLayout(
|
||||
uint8_t layout);
|
||||
|
||||
static bool validateRenderPassFormat(
|
||||
const DxvkRenderPassFormat& format);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ namespace dxvk {
|
||||
DxvkStateCacheKey shaders;
|
||||
DxvkGraphicsPipelineStateInfo gpState;
|
||||
DxvkComputePipelineStateInfo cpState;
|
||||
DxvkRenderPassFormat format;
|
||||
Sha1Hash hash;
|
||||
};
|
||||
|
||||
@ -52,7 +51,7 @@ namespace dxvk {
|
||||
*/
|
||||
struct DxvkStateCacheHeader {
|
||||
char magic[4] = { 'D', 'X', 'V', 'K' };
|
||||
uint32_t version = 11;
|
||||
uint32_t version = 12;
|
||||
uint32_t entrySize = 0; /* no longer meaningful */
|
||||
};
|
||||
|
||||
@ -89,4 +88,39 @@ namespace dxvk {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Old attachment format struct
|
||||
*/
|
||||
struct DxvkAttachmentFormatV11 {
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Old render pass format struct
|
||||
*/
|
||||
struct DxvkRenderPassFormatV11 {
|
||||
VkSampleCountFlagBits sampleCount;
|
||||
DxvkAttachmentFormatV11 depth;
|
||||
DxvkAttachmentFormatV11 color[MaxNumRenderTargets];
|
||||
|
||||
DxvkRtInfo convert() const {
|
||||
VkImageAspectFlags readOnlyAspects = 0;
|
||||
auto depthFormatInfo = imageFormatInfo(depth.format);
|
||||
|
||||
if (depth.format && depthFormatInfo) {
|
||||
readOnlyAspects = depthFormatInfo->aspectMask
|
||||
& ~vk::getWritableAspectsForLayout(depth.layout);
|
||||
}
|
||||
|
||||
std::array<VkFormat, MaxNumRenderTargets> colorFormats;
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++)
|
||||
colorFormats[i] = color[i].format;
|
||||
|
||||
return DxvkRtInfo(MaxNumRenderTargets, colorFormats.data(),
|
||||
depth.format, readOnlyAspects);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user