mirror of https://github.com/AxioDL/metaforce.git
Dramatic shader cache performance improvement
This commit is contained in:
parent
4bffe7bc8b
commit
5303b9bda1
|
@ -195,6 +195,15 @@ public:
|
|||
virtual ~IShaderBackendFactory() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Stores token and pipeline set for sharing with ref-counting
|
||||
*/
|
||||
struct ShaderPipelines
|
||||
{
|
||||
boo::GraphicsDataToken m_token;
|
||||
std::vector<boo::IShaderPipeline*> m_pipelines;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Maintains index/data file pair containing platform-dependent cached shader data
|
||||
*/
|
||||
|
@ -218,6 +227,8 @@ class ShaderCacheManager
|
|||
};
|
||||
std::vector<IndexEntry> m_entries;
|
||||
std::unordered_map<Hash, size_t> m_entryLookup;
|
||||
std::unordered_map<Hash, std::weak_ptr<ShaderPipelines>> m_pipelineLookup;
|
||||
|
||||
uint64_t m_timeHash = 0;
|
||||
void bootstrapIndex();
|
||||
ShaderCachedData lookupData(const Hash& hash);
|
||||
|
@ -239,18 +250,18 @@ public:
|
|||
* for encoding the pipeline state. This must be called before building shaders */
|
||||
void setRenderTargetSamples(unsigned samps) {m_factory->m_rtHint = samps;}
|
||||
|
||||
boo::IShaderPipeline* buildShader(const ShaderTag& tag, const std::string& source,
|
||||
std::shared_ptr<ShaderPipelines> buildShader(const ShaderTag& tag, const std::string& source,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory::Context& ctx);
|
||||
boo::IShaderPipeline* buildShader(const ShaderTag& tag, const hecl::Frontend::IR& ir,
|
||||
boo::IGraphicsDataFactory& factory);
|
||||
std::shared_ptr<ShaderPipelines> buildShader(const ShaderTag& tag, const hecl::Frontend::IR& ir,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory::Context& ctx);
|
||||
std::vector<boo::IShaderPipeline*> buildExtendedShader(const ShaderTag& tag, const std::string& source,
|
||||
boo::IGraphicsDataFactory& factory);
|
||||
std::shared_ptr<ShaderPipelines> buildExtendedShader(const ShaderTag& tag, const std::string& source,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory::Context& ctx);
|
||||
std::vector<boo::IShaderPipeline*> buildExtendedShader(const ShaderTag& tag, const hecl::Frontend::IR& ir,
|
||||
boo::IGraphicsDataFactory& factory);
|
||||
std::shared_ptr<ShaderPipelines> buildExtendedShader(const ShaderTag& tag, const hecl::Frontend::IR& ir,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory::Context& ctx);
|
||||
boo::IGraphicsDataFactory& factory);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -363,40 +363,98 @@ ShaderCacheManager::buildFromCache(const ShaderCachedData& foundData,
|
|||
return m_factory->buildShaderFromCache(foundData, ctx);
|
||||
}
|
||||
|
||||
boo::IShaderPipeline*
|
||||
std::shared_ptr<ShaderPipelines>
|
||||
ShaderCacheManager::buildShader(const ShaderTag& tag, const std::string& source,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory::Context& ctx)
|
||||
boo::IGraphicsDataFactory& factory)
|
||||
{
|
||||
boo::IShaderPipeline* ret;
|
||||
auto search = m_pipelineLookup.find(tag);
|
||||
if (search != m_pipelineLookup.cend())
|
||||
if (auto ret = search->second.lock())
|
||||
return ret;
|
||||
|
||||
std::shared_ptr<ShaderPipelines> ret = std::make_shared<ShaderPipelines>();
|
||||
ShaderCachedData foundData = lookupData(tag);
|
||||
if (foundData)
|
||||
{
|
||||
ret = buildFromCache(foundData, ctx);
|
||||
if (ret)
|
||||
ret->m_token = factory.commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
Log.report(logvisor::Info, "building cached shader '%s' %016llX", diagName.c_str(), tag.val64());
|
||||
boo::IShaderPipeline* build = buildFromCache(foundData, ctx);
|
||||
if (build)
|
||||
{
|
||||
ret->m_pipelines.push_back(build);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (ret->m_token)
|
||||
{
|
||||
m_pipelineLookup[tag] = ret;
|
||||
return ret;
|
||||
}
|
||||
Log.report(logvisor::Warning, "invalid cache read, rebuilding shader '%s'", diagName.c_str());
|
||||
}
|
||||
|
||||
ret->m_token = factory.commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
hecl::Frontend::IR ir = FE.compileSource(source, diagName);
|
||||
return buildShader(tag, ir, diagName, ctx);
|
||||
Log.report(logvisor::Info, "building shader '%s' %016llX", diagName.c_str(), tag.val64());
|
||||
FE.getDiagnostics().reset(diagName);
|
||||
boo::IShaderPipeline* build;
|
||||
addData(m_factory->buildShaderFromIR(tag, ir, FE.getDiagnostics(), ctx, build));
|
||||
ret->m_pipelines.push_back(build);
|
||||
return true;
|
||||
});
|
||||
m_pipelineLookup[tag] = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
boo::IShaderPipeline*
|
||||
std::shared_ptr<ShaderPipelines>
|
||||
ShaderCacheManager::buildShader(const ShaderTag& tag, const hecl::Frontend::IR& ir,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory::Context& ctx)
|
||||
boo::IGraphicsDataFactory& factory)
|
||||
{
|
||||
boo::IShaderPipeline* ret;
|
||||
auto search = m_pipelineLookup.find(tag);
|
||||
if (search != m_pipelineLookup.cend())
|
||||
if (auto ret = search->second.lock())
|
||||
return ret;
|
||||
|
||||
std::shared_ptr<ShaderPipelines> ret = std::make_shared<ShaderPipelines>();
|
||||
ShaderCachedData foundData = lookupData(tag);
|
||||
if (foundData)
|
||||
{
|
||||
ret = buildFromCache(foundData, ctx);
|
||||
if (ret)
|
||||
ret->m_token = factory.commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
Log.report(logvisor::Info, "building cached shader '%s' %016llX", diagName.c_str(), tag.val64());
|
||||
boo::IShaderPipeline* build = buildFromCache(foundData, ctx);
|
||||
if (build)
|
||||
{
|
||||
ret->m_pipelines.push_back(build);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (ret->m_token)
|
||||
{
|
||||
m_pipelineLookup[tag] = ret;
|
||||
return ret;
|
||||
}
|
||||
Log.report(logvisor::Warning, "invalid cache read, rebuilding shader '%s'", diagName.c_str());
|
||||
}
|
||||
|
||||
ret->m_token = factory.commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
Log.report(logvisor::Info, "building shader '%s' %016llX", diagName.c_str(), tag.val64());
|
||||
FE.getDiagnostics().reset(diagName);
|
||||
addData(m_factory->buildShaderFromIR(tag, ir, FE.getDiagnostics(), ctx, ret));
|
||||
boo::IShaderPipeline* build;
|
||||
addData(m_factory->buildShaderFromIR(tag, ir, FE.getDiagnostics(), ctx, build));
|
||||
ret->m_pipelines.push_back(build);
|
||||
return true;
|
||||
});
|
||||
m_pipelineLookup[tag] = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -415,48 +473,104 @@ ShaderCacheManager::buildExtendedFromCache(const ShaderCachedData& foundData,
|
|||
return shaders;
|
||||
}
|
||||
|
||||
std::vector<boo::IShaderPipeline*>
|
||||
std::shared_ptr<ShaderPipelines>
|
||||
ShaderCacheManager::buildExtendedShader(const ShaderTag& tag, const std::string& source,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory::Context& ctx)
|
||||
boo::IGraphicsDataFactory& factory)
|
||||
{
|
||||
std::vector<boo::IShaderPipeline*> shaders;
|
||||
ShaderCachedData foundData = lookupData(tag);
|
||||
if (foundData)
|
||||
{
|
||||
shaders = buildExtendedFromCache(foundData, ctx);
|
||||
if (shaders.size())
|
||||
return shaders;
|
||||
Log.report(logvisor::Warning, "invalid cache read, rebuilding shader '%s'", diagName.c_str());
|
||||
}
|
||||
hecl::Frontend::IR ir = FE.compileSource(source, diagName);
|
||||
return buildExtendedShader(tag, ir, diagName, ctx);
|
||||
}
|
||||
auto search = m_pipelineLookup.find(tag);
|
||||
if (search != m_pipelineLookup.cend())
|
||||
if (auto ret = search->second.lock())
|
||||
return ret;
|
||||
|
||||
std::vector<boo::IShaderPipeline*>
|
||||
ShaderCacheManager::buildExtendedShader(const ShaderTag& tag, const hecl::Frontend::IR& ir,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
std::vector<boo::IShaderPipeline*> shaders;
|
||||
std::shared_ptr<ShaderPipelines> ret = std::make_shared<ShaderPipelines>();
|
||||
ShaderCachedData foundData = lookupData(tag);
|
||||
if (foundData)
|
||||
{
|
||||
shaders = buildExtendedFromCache(foundData, ctx);
|
||||
if (shaders.size())
|
||||
return shaders;
|
||||
ret->m_token = factory.commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
Log.report(logvisor::Info, "building cached shader '%s' %016llX", diagName.c_str(), tag.val64());
|
||||
ret->m_pipelines = buildExtendedFromCache(foundData, ctx);
|
||||
if (ret->m_pipelines.size())
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (ret->m_token)
|
||||
{
|
||||
m_pipelineLookup[tag] = ret;
|
||||
return ret;
|
||||
}
|
||||
Log.report(logvisor::Warning, "invalid cache read, rebuilding shader '%s'", diagName.c_str());
|
||||
}
|
||||
shaders.reserve(m_extensions.m_extensionSlots.size());
|
||||
|
||||
hecl::Frontend::IR ir = FE.compileSource(source, diagName);
|
||||
|
||||
ret->m_token = factory.commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
ret->m_pipelines.reserve(m_extensions.m_extensionSlots.size());
|
||||
FE.getDiagnostics().reset(diagName);
|
||||
Log.report(logvisor::Info, "building shader '%s' %016llX", diagName.c_str(), tag.val64());
|
||||
ShaderCachedData data =
|
||||
m_factory->buildExtendedShaderFromIR(tag, ir, FE.getDiagnostics(), m_extensions.m_extensionSlots, ctx,
|
||||
[&](boo::IShaderPipeline* shader){shaders.push_back(shader);});
|
||||
if (shaders.size() != m_extensions.m_extensionSlots.size())
|
||||
[&](boo::IShaderPipeline* shader){ret->m_pipelines.push_back(shader);});
|
||||
if (ret->m_pipelines.size() != m_extensions.m_extensionSlots.size())
|
||||
Log.report(logvisor::Fatal, "buildShaderFromIR returned %" PRISize " times, expected %" PRISize,
|
||||
shaders.size(), m_extensions.m_extensionSlots.size());
|
||||
ret->m_pipelines.size(), m_extensions.m_extensionSlots.size());
|
||||
addData(data);
|
||||
return shaders;
|
||||
return true;
|
||||
});
|
||||
m_pipelineLookup[tag] = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<ShaderPipelines>
|
||||
ShaderCacheManager::buildExtendedShader(const ShaderTag& tag, const hecl::Frontend::IR& ir,
|
||||
const std::string& diagName,
|
||||
boo::IGraphicsDataFactory& factory)
|
||||
{
|
||||
auto search = m_pipelineLookup.find(tag);
|
||||
if (search != m_pipelineLookup.cend())
|
||||
if (auto ret = search->second.lock())
|
||||
return ret;
|
||||
|
||||
std::shared_ptr<ShaderPipelines> ret = std::make_shared<ShaderPipelines>();
|
||||
ShaderCachedData foundData = lookupData(tag);
|
||||
if (foundData)
|
||||
{
|
||||
ret->m_token = factory.commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
Log.report(logvisor::Info, "building cached shader '%s' %016llX", diagName.c_str(), tag.val64());
|
||||
ret->m_pipelines = buildExtendedFromCache(foundData, ctx);
|
||||
if (ret->m_pipelines.size())
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (ret->m_token)
|
||||
{
|
||||
m_pipelineLookup[tag] = ret;
|
||||
return ret;
|
||||
}
|
||||
Log.report(logvisor::Warning, "invalid cache read, rebuilding shader '%s'", diagName.c_str());
|
||||
}
|
||||
|
||||
ret->m_token = factory.commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
ret->m_pipelines.reserve(m_extensions.m_extensionSlots.size());
|
||||
FE.getDiagnostics().reset(diagName);
|
||||
Log.report(logvisor::Info, "building shader '%s' %016llX", diagName.c_str(), tag.val64());
|
||||
ShaderCachedData data =
|
||||
m_factory->buildExtendedShaderFromIR(tag, ir, FE.getDiagnostics(), m_extensions.m_extensionSlots, ctx,
|
||||
[&](boo::IShaderPipeline* shader){ret->m_pipelines.push_back(shader);});
|
||||
if (ret->m_pipelines.size() != m_extensions.m_extensionSlots.size())
|
||||
Log.report(logvisor::Fatal, "buildShaderFromIR returned %" PRISize " times, expected %" PRISize,
|
||||
ret->m_pipelines.size(), m_extensions.m_extensionSlots.size());
|
||||
addData(data);
|
||||
return true;
|
||||
});
|
||||
m_pipelineLookup[tag] = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,12 +74,6 @@ struct HECLApplicationCallback : boo::IApplicationCallback
|
|||
std::unique_lock<std::mutex> innerLk(initmt);
|
||||
boo::IGraphicsDataFactory* gfxF = m_mainWindow->getLoadContextDataFactory();
|
||||
|
||||
boo::GraphicsDataToken data =
|
||||
gfxF->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
boo::SWindowRect mainWindowRect = m_mainWindow->getWindowFrame();
|
||||
renderTex = ctx.newRenderTexture(mainWindowRect.size[0], mainWindowRect.size[1], false, false);
|
||||
|
||||
/* HECL managers */
|
||||
hecl::Runtime::FileStoreManager fileMgr(app->getUniqueName());
|
||||
hecl::Runtime::ShaderCacheManager shaderMgr(fileMgr, gfxF);
|
||||
|
@ -88,8 +82,14 @@ struct HECLApplicationCallback : boo::IApplicationCallback
|
|||
static std::string testShader = "HECLOpaque(Texture(0, UV(0)))";
|
||||
//static std::string testShader = "HECLOpaque(vec4(1.0,1.0,1.0,1.0))";
|
||||
hecl::Runtime::ShaderTag testShaderTag(testShader, 0, 1, 0, 0, 0, boo::Primitive::TriStrips, false, false, false);
|
||||
boo::IShaderPipeline* testShaderObj =
|
||||
shaderMgr.buildShader(testShaderTag, testShader, "testShader", ctx);
|
||||
std::shared_ptr<hecl::Runtime::ShaderPipelines> testShaderObj =
|
||||
shaderMgr.buildShader(testShaderTag, testShader, "testShader", *gfxF);
|
||||
|
||||
boo::GraphicsDataToken data =
|
||||
gfxF->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
||||
{
|
||||
boo::SWindowRect mainWindowRect = m_mainWindow->getWindowFrame();
|
||||
renderTex = ctx.newRenderTexture(mainWindowRect.size[0], mainWindowRect.size[1], false, false);
|
||||
|
||||
/* Generate meta structure (usually statically serialized) */
|
||||
hecl::HMDLMeta testMeta;
|
||||
|
@ -146,7 +146,7 @@ struct HECLApplicationCallback : boo::IApplicationCallback
|
|||
vubo = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(VertexUBO), 1);
|
||||
|
||||
/* Assemble data binding */
|
||||
binding = testData.newShaderDataBindng(ctx, testShaderObj, 1, (boo::IGraphicsBuffer**)&vubo, nullptr, 1, &texture);
|
||||
binding = testData.newShaderDataBindng(ctx, testShaderObj->m_pipelines[0], 1, (boo::IGraphicsBuffer**)&vubo, nullptr, 1, &texture);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue