summaryrefslogtreecommitdiffstats
path: root/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderShaderCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderShaderCache.cpp')
m---------src/Runtime/ogl-runtime0
-rw-r--r--src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderShaderCache.cpp770
2 files changed, 0 insertions, 770 deletions
diff --git a/src/Runtime/ogl-runtime b/src/Runtime/ogl-runtime
new file mode 160000
+Subproject 2025912174c4cf99270b7439ec3b021e1d089ae
diff --git a/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderShaderCache.cpp b/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderShaderCache.cpp
deleted file mode 100644
index 77d4ee64..00000000
--- a/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderShaderCache.cpp
+++ /dev/null
@@ -1,770 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2008-2012 NVIDIA Corporation.
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt 3D Studio.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "Qt3DSRenderShaderCache.h"
-#include "render/Qt3DSRenderContext.h"
-#include "foundation/Qt3DSContainers.h"
-#include "foundation/Qt3DSAtomic.h"
-#include "StringTools.h"
-#include "foundation/XML.h"
-#include "foundation/IOStreams.h"
-#include "foundation/StringConversionImpl.h"
-#include "Qt3DSRenderInputStreamFactory.h"
-#include "foundation/FileTools.h"
-#include "render/Qt3DSRenderShaderProgram.h"
-#include "Qt3DSRenderer.h"
-#include <memory>
-#include "foundation/Qt3DSTime.h"
-#include "foundation/Qt3DSPerfTimer.h"
-#include "EASTL/sort.h"
-
-#include <QRegularExpression>
-#include <QString>
-
-using namespace qt3ds::render;
-
-namespace {
-using qt3ds::render::NVRenderContextScopedProperty;
-const char *TessellationEnabledStr = "TessellationStageEnabled";
-const char *GeometryEnabledStr = "GeometryStageEnabled";
-inline void AppendFlagValue(Qt3DSString &inStr, const char *flag)
-{
- if (inStr.length())
- inStr.append(QLatin1Char(','));
- inStr.append(flag);
-}
-inline void CacheFlagsToStr(const SShaderCacheProgramFlags &inFlags, Qt3DSString &inString)
-{
- inString.clear();
- if (inFlags.IsTessellationEnabled())
- AppendFlagValue(inString, TessellationEnabledStr);
- if (inFlags.IsGeometryShaderEnabled())
- AppendFlagValue(inString, GeometryEnabledStr);
-}
-
-struct ShaderType
-{
- enum Enum { Vertex, TessControl, TessEval, Fragment, Geometry, Compute };
-};
-
-inline ShaderType::Enum StringToShaderType(Qt3DSString &inShaderType)
-{
- ShaderType::Enum retval = ShaderType::Vertex;
-
- if (inShaderType.size() == 0)
- return retval;
-
- if (!inShaderType.compare("VertexCode"))
- retval = ShaderType::Vertex;
- else if (!inShaderType.compare("FragmentCode"))
- retval = ShaderType::Fragment;
- else if (!inShaderType.compare("TessControlCode"))
- retval = ShaderType::TessControl;
- else if (!inShaderType.compare("TessEvalCode"))
- retval = ShaderType::TessEval;
- else if (!inShaderType.compare("GeometryCode"))
- retval = ShaderType::Geometry;
- else
- QT3DS_ASSERT(false);
-
- return retval;
-}
-
-inline SShaderCacheProgramFlags CacheFlagsToStr(const Qt3DSString &inString)
-{
- SShaderCacheProgramFlags retval;
- if (inString.indexOf(TessellationEnabledStr) != Qt3DSString::npos)
- retval.SetTessellationEnabled(true);
- if (inString.indexOf(GeometryEnabledStr) != Qt3DSString::npos)
- retval.SetGeometryShaderEnabled(true);
- return retval;
-}
-
-typedef eastl::pair<const char *, NVRenderContextValues::Enum> TStringToContextValuePair;
-
-/*GLES2 = 1 << 0,
-GL2 = 1 << 1,
-GLES3 = 1 << 2,
-GL3 = 1 << 3,
-GL4 = 1 << 4,
-NullContext = 1 << 5,*/
-TStringToContextValuePair g_StringToContextTypeValue[] = {
- TStringToContextValuePair("GLES2", NVRenderContextValues::GLES2),
- TStringToContextValuePair("GL2", NVRenderContextValues::GL2),
- TStringToContextValuePair("GLES3", NVRenderContextValues::GLES3),
- TStringToContextValuePair("GLES3PLUS", NVRenderContextValues::GLES3PLUS),
- TStringToContextValuePair("GL3", NVRenderContextValues::GL3),
- TStringToContextValuePair("GL4", NVRenderContextValues::GL4),
- TStringToContextValuePair("NullContext", NVRenderContextValues::NullContext),
-};
-
-size_t g_NumStringToContextValueEntries =
- sizeof(g_StringToContextTypeValue) / sizeof(*g_StringToContextTypeValue);
-
-inline void ContextTypeToString(qt3ds::render::NVRenderContextType inType,
- Qt3DSString &outContextType)
-{
- outContextType.clear();
- for (size_t idx = 0, end = g_NumStringToContextValueEntries; idx < end; ++idx) {
- if (inType & g_StringToContextTypeValue[idx].second) {
- if (outContextType.size())
- outContextType.append('|');
- outContextType.append(g_StringToContextTypeValue[idx].first);
- }
- }
-}
-
-inline qt3ds::render::NVRenderContextType StringToContextType(const Qt3DSString &inContextType)
-{
- qt3ds::render::NVRenderContextType retval;
- char tempBuffer[128];
- memZero(tempBuffer, 128);
- const QString::size_type lastTempBufIdx = 127;
- QString::size_type pos = 0, lastpos = 0;
- if (inContextType.size() == 0)
- return retval;
-
- do {
- pos = int(inContextType.indexOf(QLatin1Char('|'), lastpos));
- if (pos == Qt3DSString::npos)
- pos = int(inContextType.size());
- {
-
- QString::size_type sectionLen = NVMin(pos - lastpos, lastTempBufIdx);
- qt3ds::intrinsics::memCopy(tempBuffer, inContextType.toUtf8().constData() + lastpos,
- sectionLen);
- tempBuffer[lastTempBufIdx] = 0;
- for (size_t idx = 0, end = g_NumStringToContextValueEntries; idx < end; ++idx) {
- if (strcmp(g_StringToContextTypeValue[idx].first, tempBuffer) == 0)
- retval = retval | g_StringToContextTypeValue[idx].second;
- }
- }
- // iterate past the bar
- ++pos;
- lastpos = pos;
- } while (pos < inContextType.size() && pos != Qt3DSString::npos);
-
- return retval;
-}
-
-struct SShaderCacheKey
-{
- CRegisteredString m_Key;
- eastl::vector<SShaderPreprocessorFeature> m_Features;
- size_t m_HashCode;
-
- SShaderCacheKey(CRegisteredString key = CRegisteredString())
- : m_Key(key)
- , m_HashCode(0)
- {
- }
-
- SShaderCacheKey(const SShaderCacheKey &other)
- : m_Key(other.m_Key)
- , m_Features(other.m_Features)
- , m_HashCode(other.m_HashCode)
- {
- }
-
- SShaderCacheKey &operator=(const SShaderCacheKey &other)
- {
- m_Key = other.m_Key;
- m_Features = other.m_Features;
- m_HashCode = other.m_HashCode;
- return *this;
- }
-
- void GenerateHashCode()
- {
- m_HashCode = m_Key.hash();
- m_HashCode = m_HashCode
- ^ HashShaderFeatureSet(toDataRef(m_Features.data(), (QT3DSU32)m_Features.size()));
- }
- bool operator==(const SShaderCacheKey &inOther) const
- {
- return m_Key == inOther.m_Key && m_Features == inOther.m_Features;
- }
-};
-}
-
-namespace eastl {
-template <>
-struct hash<SShaderCacheKey>
-{
- size_t operator()(const SShaderCacheKey &inKey) const { return inKey.m_HashCode; }
-};
-}
-
-namespace {
-
-struct ShaderCache : public IShaderCache
-{
- typedef nvhash_map<SShaderCacheKey, NVScopedRefCounted<NVRenderShaderProgram>> TShaderMap;
- NVRenderContext &m_RenderContext;
- IPerfTimer &m_PerfTimer;
- TShaderMap m_Shaders;
- Qt3DSString m_CacheFilePath;
- Qt3DSString m_VertexCode;
- Qt3DSString m_TessCtrlCode;
- Qt3DSString m_TessEvalCode;
- Qt3DSString m_GeometryCode;
- Qt3DSString m_FragmentCode;
- Qt3DSString m_InsertStr;
- Qt3DSString m_FlagString;
- Qt3DSString m_ContextTypeString;
- SShaderCacheKey m_TempKey;
-
- NVScopedRefCounted<IDOMWriter> m_ShaderCache;
- IInputStreamFactory &m_InputStreamFactory;
- bool m_ShaderCompilationEnabled;
- volatile QT3DSI32 mRefCount;
-
- ShaderCache(NVRenderContext &ctx, IInputStreamFactory &inInputStreamFactory,
- IPerfTimer &inPerfTimer)
- : m_RenderContext(ctx)
- , m_PerfTimer(inPerfTimer)
- , m_Shaders(ctx.GetAllocator(), "ShaderCache::m_Shaders")
- , m_InputStreamFactory(inInputStreamFactory)
- , m_ShaderCompilationEnabled(true)
- , mRefCount(0)
- {
- }
- QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext.GetAllocator())
-
- NVRenderShaderProgram *GetProgram(CRegisteredString inKey,
- NVConstDataRef<SShaderPreprocessorFeature> inFeatures) override
- {
- m_TempKey.m_Key = inKey;
- m_TempKey.m_Features.assign(inFeatures.begin(), inFeatures.end());
- m_TempKey.GenerateHashCode();
- TShaderMap::iterator theIter = m_Shaders.find(m_TempKey);
- if (theIter != m_Shaders.end())
- return theIter->second;
- return NULL;
- }
-
- void AddBackwardCompatibilityDefines(ShaderType::Enum shaderType)
- {
- if (shaderType == ShaderType::Vertex || shaderType == ShaderType::TessControl
- || shaderType == ShaderType::TessEval || shaderType == ShaderType::Geometry) {
- m_InsertStr += "#define attribute in\n";
- m_InsertStr += "#define varying out\n";
- } else if (shaderType == ShaderType::Fragment) {
- m_InsertStr += "#define varying in\n";
- m_InsertStr += "#define texture2D texture\n";
- m_InsertStr += "#define gl_FragColor fragOutput\n";
-
- if (m_RenderContext.IsAdvancedBlendHwSupportedKHR())
- m_InsertStr += "layout(blend_support_all_equations) out;\n";
-
- m_InsertStr += "#ifndef NO_FRAG_OUTPUT\n";
- m_InsertStr += "out vec4 fragOutput;\n";
- m_InsertStr += "#endif\n";
- }
- }
-
- void AddShaderExtensionStrings(ShaderType::Enum shaderType, bool isGLES)
- {
- if (isGLES) {
- if (m_RenderContext.IsStandardDerivativesSupported())
- m_InsertStr += "#extension GL_OES_standard_derivatives : enable\n";
- else
- m_InsertStr += "#extension GL_OES_standard_derivatives : disable\n";
- }
-
- if (IQt3DSRenderer::IsGlEs3Context(m_RenderContext.GetRenderContextType())) {
- if (shaderType == ShaderType::TessControl || shaderType == ShaderType::TessEval) {
- m_InsertStr += "#extension GL_EXT_tessellation_shader : enable\n";
- } else if (shaderType == ShaderType::Geometry) {
- m_InsertStr += "#extension GL_EXT_geometry_shader : enable\n";
- } else if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment) {
- if (m_RenderContext.GetRenderBackendCap(render::NVRenderBackend::NVRenderBackendCaps::gpuShader5))
- m_InsertStr += "#extension GL_EXT_gpu_shader5 : enable\n";
- if (m_RenderContext.IsAdvancedBlendHwSupportedKHR())
- m_InsertStr += "#extension GL_KHR_blend_equation_advanced : enable\n";
- }
- } else {
- if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment
- || shaderType == ShaderType::Geometry) {
- if (m_RenderContext.GetRenderContextType() != NVRenderContextValues::GLES2) {
- m_InsertStr += "#extension GL_ARB_gpu_shader5 : enable\n";
- m_InsertStr += "#extension GL_ARB_shading_language_420pack : enable\n";
- }
- if (isGLES && m_RenderContext.IsTextureLodSupported())
- m_InsertStr += "#extension GL_EXT_shader_texture_lod : enable\n";
- if (m_RenderContext.IsShaderImageLoadStoreSupported())
- m_InsertStr += "#extension GL_ARB_shader_image_load_store : enable\n";
- if (m_RenderContext.IsAtomicCounterBufferSupported())
- m_InsertStr += "#extension GL_ARB_shader_atomic_counters : enable\n";
- if (m_RenderContext.IsStorageBufferSupported())
- m_InsertStr += "#extension GL_ARB_shader_storage_buffer_object : enable\n";
- if (m_RenderContext.IsAdvancedBlendHwSupportedKHR())
- m_InsertStr += "#extension GL_KHR_blend_equation_advanced : enable\n";
- }
- }
- }
-
- void AddShaderPreprocessor(Qt3DSString &str, CRegisteredString inKey,
- ShaderType::Enum shaderType,
- NVConstDataRef<SShaderPreprocessorFeature> inFeatures)
- {
- // Don't use shading language version returned by the driver as it might
- // differ from the context version. Instead use the context type to specify
- // the version string.
- bool isGlES = IQt3DSRenderer::IsGlEsContext(m_RenderContext.GetRenderContextType());
- m_InsertStr.clear();
- int minor = m_RenderContext.format().minorVersion();
- QString versionStr;
- QTextStream stream(&versionStr);
- stream << "#version ";
- const QT3DSU32 type = (QT3DSU32)m_RenderContext.GetRenderContextType();
- switch (type) {
- case NVRenderContextValues::GLES2:
- stream << "1" << minor << "0\n";
- break;
- case NVRenderContextValues::GL2:
- stream << "1" << minor << "0\n";
- break;
- case NVRenderContextValues::GLES3PLUS:
- case NVRenderContextValues::GLES3:
- stream << "3" << minor << "0 es\n";
- break;
- case NVRenderContextValues::GL3:
- if (minor == 3)
- stream << "3" << minor << "0\n";
- else
- stream << "1" << 3 + minor << "0\n";
- break;
- case NVRenderContextValues::GL4:
- stream << "4" << minor << "0\n";
- break;
- default:
- QT3DS_ASSERT(false);
- break;
- }
-
- m_InsertStr.append(versionStr.toLatin1().data());
-
- if (inFeatures.size()) {
- for (QT3DSU32 idx = 0, end = inFeatures.size(); idx < end; ++idx) {
- SShaderPreprocessorFeature feature(inFeatures[idx]);
- m_InsertStr.append("#define ");
- m_InsertStr.append(inFeatures[idx].m_Name.c_str());
- m_InsertStr.append(" ");
- m_InsertStr.append(feature.m_Enabled ? "1" : "0");
- m_InsertStr.append("\n");
- }
- }
-
- if (isGlES) {
- if (!IQt3DSRenderer::IsGlEs3Context(m_RenderContext.GetRenderContextType())) {
- if (shaderType == ShaderType::Fragment) {
- m_InsertStr += "#define fragOutput gl_FragData[0]\n";
- }
- } else {
- m_InsertStr += "#define texture2D texture\n";
- }
-
- // add extenions strings before any other non-processor token
- AddShaderExtensionStrings(shaderType, isGlES);
-
- // add precision qualifier depending on backend
- if (IQt3DSRenderer::IsGlEs3Context(m_RenderContext.GetRenderContextType())) {
- m_InsertStr.append("precision highp float;\n"
- "precision highp int;\n");
- if( m_RenderContext.GetRenderBackendCap(render::NVRenderBackend::NVRenderBackendCaps::gpuShader5) ) {
- m_InsertStr.append("precision mediump sampler2D;\n"
- "precision mediump sampler2DArray;\n"
- "precision mediump sampler2DShadow;\n");
- if (m_RenderContext.IsShaderImageLoadStoreSupported()) {
- m_InsertStr.append("precision mediump image2D;\n");
- }
- }
-
- AddBackwardCompatibilityDefines(shaderType);
- } else {
- // GLES2
- m_InsertStr.append("precision mediump float;\n"
- "precision mediump int;\n"
- "#define texture texture2D\n");
- if (m_RenderContext.IsTextureLodSupported())
- m_InsertStr.append("#define textureLod texture2DLodEXT\n");
- else
- m_InsertStr.append("#define textureLod(s, co, lod) texture2D(s, co)\n");
- }
- } else {
- if (!IQt3DSRenderer::IsGl2Context(m_RenderContext.GetRenderContextType())) {
- m_InsertStr += "#define texture2D texture\n";
-
- AddShaderExtensionStrings(shaderType, isGlES);
-
- m_InsertStr += "#if __VERSION__ >= 330\n";
-
- AddBackwardCompatibilityDefines(shaderType);
-
- m_InsertStr += "#else\n";
- if (shaderType == ShaderType::Fragment) {
- m_InsertStr += "#define fragOutput gl_FragData[0]\n";
- }
- m_InsertStr += "#endif\n";
- }
- }
-
- if (inKey.IsValid()) {
- m_InsertStr += "//Shader name -";
- m_InsertStr += inKey.c_str();
- m_InsertStr += "\n";
- }
-
- if (shaderType == ShaderType::TessControl) {
- m_InsertStr += "#define TESSELLATION_CONTROL_SHADER 1\n";
- m_InsertStr += "#define TESSELLATION_EVALUATION_SHADER 0\n";
- } else if (shaderType == ShaderType::TessEval) {
- m_InsertStr += "#define TESSELLATION_CONTROL_SHADER 0\n";
- m_InsertStr += "#define TESSELLATION_EVALUATION_SHADER 1\n";
- }
-
- str.insert(0, m_InsertStr);
- }
- // Compile this program overwriting any existing ones.
- NVRenderShaderProgram *
- ForceCompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag,
- const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom,
- const SShaderCacheProgramFlags &inFlags,
- NVConstDataRef<SShaderPreprocessorFeature> inFeatures,
- bool separableProgram, bool fromDisk = false) override
- {
- if (m_ShaderCompilationEnabled == false)
- return NULL;
- SShaderCacheKey tempKey(inKey);
- tempKey.m_Features.assign(inFeatures.begin(), inFeatures.end());
- tempKey.GenerateHashCode();
-
- eastl::pair<TShaderMap::iterator, bool> theInserter = m_Shaders.insert(tempKey);
- if (fromDisk) {
- qCInfo(TRACE_INFO) << "Loading from persistent shader cache: '<"
- << tempKey.m_Key << ">'";
- } else {
- qCInfo(TRACE_INFO) << "Compiling into shader cache: '"
- << tempKey.m_Key << ">'";
- }
-
- if (!inVert)
- inVert = "";
- if (!inTessCtrl)
- inTessCtrl = "";
- if (!inTessEval)
- inTessEval = "";
- if (!inGeom)
- inGeom = "";
- if (!inFrag)
- inFrag = "";
-
- SStackPerfTimer __perfTimer(m_PerfTimer, "Shader Compilation");
- m_VertexCode.assign(inVert);
- m_TessCtrlCode.assign(inTessCtrl);
- m_TessEvalCode.assign(inTessEval);
- m_GeometryCode.assign(inGeom);
- m_FragmentCode.assign(inFrag);
- // Add defines and such so we can write unified shaders that work across platforms.
- // vertex and fragment shaders are optional for separable shaders
- if (!separableProgram || !m_VertexCode.isEmpty())
- AddShaderPreprocessor(m_VertexCode, inKey, ShaderType::Vertex, inFeatures);
- if (!separableProgram || !m_FragmentCode.isEmpty())
- AddShaderPreprocessor(m_FragmentCode, inKey, ShaderType::Fragment, inFeatures);
- // optional shaders
- if (inFlags.IsTessellationEnabled()) {
- QT3DS_ASSERT(m_TessCtrlCode.size() && m_TessEvalCode.size());
- AddShaderPreprocessor(m_TessCtrlCode, inKey, ShaderType::TessControl, inFeatures);
- AddShaderPreprocessor(m_TessEvalCode, inKey, ShaderType::TessEval, inFeatures);
- }
- if (inFlags.IsGeometryShaderEnabled())
- AddShaderPreprocessor(m_GeometryCode, inKey, ShaderType::Geometry, inFeatures);
-
- theInserter.first->second =
- m_RenderContext
- .CompileSource(inKey, m_VertexCode.c_str(), QT3DSU32(m_VertexCode.size()),
- m_FragmentCode.c_str(), QT3DSU32(m_FragmentCode.size()),
- m_TessCtrlCode.c_str(), QT3DSU32(m_TessCtrlCode.size()),
- m_TessEvalCode.c_str(), QT3DSU32(m_TessEvalCode.size()),
- m_GeometryCode.c_str(), QT3DSU32(m_GeometryCode.size()),
- separableProgram).mShader;
- if (theInserter.first->second) {
- if (m_ShaderCache) {
- IDOMWriter::Scope __writeScope(*m_ShaderCache, "Program");
- m_ShaderCache->Att("key", inKey.c_str());
- CacheFlagsToStr(inFlags, m_FlagString);
- if (m_FlagString.size())
- m_ShaderCache->Att("glflags", m_FlagString.c_str());
- // write out the GL version.
- {
- qt3ds::render::NVRenderContextType theContextType =
- m_RenderContext.GetRenderContextType();
- ContextTypeToString(theContextType, m_ContextTypeString);
- m_ShaderCache->Att("gl-context-type", m_ContextTypeString.c_str());
- }
- if (inFeatures.size()) {
- IDOMWriter::Scope __writeScope(*m_ShaderCache, "Features");
- for (QT3DSU32 idx = 0, end = inFeatures.size(); idx < end; ++idx) {
- m_ShaderCache->Att(inFeatures[idx].m_Name, inFeatures[idx].m_Enabled);
- }
- }
-
- {
- IDOMWriter::Scope __writeScope(*m_ShaderCache, "VertexCode");
- m_ShaderCache->Value(inVert);
- }
- {
- IDOMWriter::Scope __writeScope(*m_ShaderCache, "FragmentCode");
- m_ShaderCache->Value(inFrag);
- }
- if (m_TessCtrlCode.size()) {
- IDOMWriter::Scope __writeScope(*m_ShaderCache, "TessControlCode");
- m_ShaderCache->Value(inTessCtrl);
- }
- if (m_TessEvalCode.size()) {
- IDOMWriter::Scope __writeScope(*m_ShaderCache, "TessEvalCode");
- m_ShaderCache->Value(inTessEval);
- }
- if (m_GeometryCode.size()) {
- IDOMWriter::Scope __writeScope(*m_ShaderCache, "GeometryCode");
- m_ShaderCache->Value(inGeom);
- }
- }
- }
- return theInserter.first->second;
- }
-
- virtual NVRenderShaderProgram *
- CompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag,
- const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom,
- const SShaderCacheProgramFlags &inFlags,
- NVConstDataRef<SShaderPreprocessorFeature> inFeatures, bool separableProgram) override
- {
- NVRenderShaderProgram *theProgram = GetProgram(inKey, inFeatures);
- if (theProgram)
- return theProgram;
-
- NVRenderShaderProgram *retval =
- ForceCompileProgram(inKey, inVert, inFrag, inTessCtrl, inTessEval, inGeom, inFlags,
- inFeatures, separableProgram);
- if (m_CacheFilePath.c_str() && m_ShaderCache && m_ShaderCompilationEnabled) {
- CFileSeekableIOStream theStream(m_CacheFilePath.c_str(), FileWriteFlags());
- if (theStream.IsOpen()) {
- NVScopedRefCounted<IStringTable> theStringTable(
- IStringTable::CreateStringTable(m_RenderContext.GetAllocator()));
- CDOMSerializer::WriteXMLHeader(theStream);
- CDOMSerializer::Write(m_RenderContext.GetAllocator(),
- *m_ShaderCache->GetTopElement(), theStream, *theStringTable);
- }
- }
- return retval;
- }
-
- void BootupDOMWriter()
- {
- NVScopedRefCounted<IStringTable> theStringTable(
- IStringTable::CreateStringTable(m_RenderContext.GetAllocator()));
- m_ShaderCache = IDOMWriter::CreateDOMWriter(m_RenderContext.GetAllocator(),
- "Qt3DSShaderCache", theStringTable)
- .first;
- m_ShaderCache->Att("cache_version", IShaderCache::GetShaderVersion());
- }
-
- void SetShaderCachePersistenceEnabled(const char8_t *inDirectory) override
- {
- if (inDirectory == NULL) {
- m_ShaderCache = NULL;
- return;
- }
- BootupDOMWriter();
- m_CacheFilePath = QDir(inDirectory).filePath(GetShaderCacheFileName());
-
- NVScopedRefCounted<IRefCountedInputStream> theInStream =
- m_InputStreamFactory.GetStreamForFile(m_CacheFilePath.c_str());
- if (theInStream) {
- SStackPerfTimer __perfTimer(m_PerfTimer, "ShaderCache - Load");
- NVScopedRefCounted<IStringTable> theStringTable(
- IStringTable::CreateStringTable(m_RenderContext.GetAllocator()));
- NVScopedRefCounted<IDOMFactory> theFactory(
- IDOMFactory::CreateDOMFactory(m_RenderContext.GetAllocator(), theStringTable));
- eastl::vector<SShaderPreprocessorFeature> theFeatures;
-
- SDOMElement *theElem = CDOMSerializer::Read(*theFactory, *theInStream).second;
- if (theElem) {
- NVScopedRefCounted<IDOMReader> theReader = IDOMReader::CreateDOMReader(
- m_RenderContext.GetAllocator(), *theElem, theStringTable, theFactory);
- QT3DSU32 theAttValue = 0;
- theReader->Att("cache_version", theAttValue);
- if (theAttValue == IShaderCache::GetShaderVersion()) {
- Qt3DSString loadVertexData;
- Qt3DSString loadFragmentData;
- Qt3DSString loadTessControlData;
- Qt3DSString loadTessEvalData;
- Qt3DSString loadGeometryData;
- Qt3DSString shaderTypeString;
- IStringTable &theStringTable(m_RenderContext.GetStringTable());
- for (bool success = theReader->MoveToFirstChild(); success;
- success = theReader->MoveToNextSibling()) {
- const char8_t *theKeyStr = NULL;
- theReader->UnregisteredAtt("key", theKeyStr);
-
- CRegisteredString theKey = theStringTable.RegisterStr(theKeyStr);
- if (theKey.IsValid()) {
- m_FlagString.clear();
- const char8_t *theFlagStr = "";
- SShaderCacheProgramFlags theFlags;
- if (theReader->UnregisteredAtt("glflags", theFlagStr)) {
- m_FlagString.assign(theFlagStr);
- theFlags = CacheFlagsToStr(m_FlagString);
- }
-
- m_ContextTypeString.clear();
- if (theReader->UnregisteredAtt("gl-context-type", theFlagStr))
- m_ContextTypeString.assign(theFlagStr);
-
- theFeatures.clear();
- {
- IDOMReader::Scope __featureScope(*theReader);
- if (theReader->MoveToFirstChild("Features")) {
- for (SDOMAttribute *theAttribute =
- theReader->GetFirstAttribute();
- theAttribute;
- theAttribute = theAttribute->m_NextAttribute) {
- bool featureValue = false;
- StringConversion<bool>().StrTo(theAttribute->m_Value,
- featureValue);
- theFeatures.push_back(SShaderPreprocessorFeature(
- theStringTable.RegisterStr(
- theAttribute->m_Name.c_str()),
- featureValue));
- }
- }
- }
-
- qt3ds::render::NVRenderContextType theContextType =
- StringToContextType(m_ContextTypeString);
- if (((QT3DSU32)theContextType != 0)
- && (theContextType & m_RenderContext.GetRenderContextType())
- == theContextType) {
- IDOMReader::Scope __readerScope(*theReader);
- loadVertexData.clear();
- loadFragmentData.clear();
- loadTessControlData.clear();
- loadTessEvalData.clear();
- loadGeometryData.clear();
-
- // Vertex *MUST* be the first
- // Todo deal with pure compute shader programs
- if (theReader->MoveToFirstChild("VertexCode")) {
- const char8_t *theValue = NULL;
- theReader->Value(theValue);
- loadVertexData.assign(theValue);
- while (theReader->MoveToNextSibling()) {
- theReader->Value(theValue);
-
- shaderTypeString.assign(
- theReader->GetElementName().c_str());
- ShaderType::Enum shaderType =
- StringToShaderType(shaderTypeString);
-
- if (shaderType == ShaderType::Fragment)
- loadFragmentData.assign(theValue);
- else if (shaderType == ShaderType::TessControl)
- loadTessControlData.assign(theValue);
- else if (shaderType == ShaderType::TessEval)
- loadTessEvalData.assign(theValue);
- else if (shaderType == ShaderType::Geometry)
- loadGeometryData.assign(theValue);
- }
- }
-
- if (loadVertexData.size()
- && (loadFragmentData.size() || loadGeometryData.size())) {
-
- NVRenderShaderProgram *theShader = ForceCompileProgram(
- theKey, loadVertexData.c_str(), loadFragmentData.c_str(),
- loadTessControlData.c_str(), loadTessEvalData.c_str(),
- loadGeometryData.c_str(), theFlags,
- qt3ds::foundation::toDataRef(theFeatures.data(),
- (QT3DSU32)theFeatures.size()),
- false, true /*fromDisk*/);
- // If something doesn't save or load correctly, get the runtime
- // to re-generate.
- if (!theShader)
- m_Shaders.erase(theKey);
- }
- }
- }
- }
- }
- }
- }
- }
-
- bool IsShaderCachePersistenceEnabled() const override { return m_ShaderCache != NULL; }
-
- void SetShaderCompilationEnabled(bool inEnableShaderCompilation) override
- {
- m_ShaderCompilationEnabled = inEnableShaderCompilation;
- }
-};
-}
-
-size_t qt3ds::render::HashShaderFeatureSet(NVConstDataRef<SShaderPreprocessorFeature> inFeatureSet)
-{
- size_t retval(0);
- for (QT3DSU32 idx = 0, end = inFeatureSet.size(); idx < end; ++idx) {
- // From previous implementation, it seems we need to ignore the order of the features.
- // But we need to bind the feature flag together with its name, so that the flags will
- // influence
- // the final hash not only by the true-value count.
- retval = retval
- ^ (inFeatureSet[idx].m_Name.hash() * eastl::hash<bool>()(inFeatureSet[idx].m_Enabled));
- }
- return retval;
-}
-
-bool SShaderPreprocessorFeature::operator<(const SShaderPreprocessorFeature &other) const
-{
- return strcmp(m_Name.c_str(), other.m_Name.c_str()) < 0;
-}
-
-bool SShaderPreprocessorFeature::operator==(const SShaderPreprocessorFeature &other) const
-{
- return m_Name == other.m_Name && m_Enabled == other.m_Enabled;
-}
-
-IShaderCache &IShaderCache::CreateShaderCache(NVRenderContext &inContext,
- IInputStreamFactory &inInputStreamFactory,
- IPerfTimer &inPerfTimer)
-{
- return *QT3DS_NEW(inContext.GetAllocator(), ShaderCache)(inContext, inInputStreamFactory,
- inPerfTimer);
-}