summaryrefslogtreecommitdiffstats
path: root/src/render/materialsystem/shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/materialsystem/shader.cpp')
-rw-r--r--src/render/materialsystem/shader.cpp365
1 files changed, 37 insertions, 328 deletions
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index 0d4b5edba..00d9d334f 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -50,6 +50,7 @@
#include <Qt3DRender/private/qshaderprogram_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DRender/private/managers_p.h>
QT_BEGIN_NAMESPACE
@@ -83,47 +84,23 @@ const int Shader::skinningPaletteNameId = StringToInt::lookupId(QLatin1String("s
Shader::Shader()
: BackendNode(ReadWrite)
- , m_isLoaded(false)
- , m_dna(0)
- , m_oldDna(0)
- , m_graphicsContext(nullptr)
- , m_status(QShaderProgram::NotReady)
, m_requiresFrontendSync(false)
+ , m_status(QShaderProgram::NotReady)
+ , m_dirty(false)
{
m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1);
}
Shader::~Shader()
{
- // TO DO: ShaderProgram is leaked as of now
- // Fix that taking care that they may be shared given a same dna
- if (m_graphicsContext)
- QObject::disconnect(m_contextConnection);
}
void Shader::cleanup()
{
- // Remove this shader from the hash in the graphics context so
- // nothing tries to use it after it has been recycled
- {
- QMutexLocker lock(&m_mutex);
- if (m_graphicsContext)
- m_graphicsContext->removeShaderProgramReference(this);
- m_graphicsContext = nullptr;
- QObject::disconnect(m_contextConnection);
- }
-
QBackendNode::setEnabled(false);
- m_isLoaded = false;
- m_dna = 0;
- m_oldDna = 0;
- m_uniformsNames.clear();
- m_attributesNames.clear();
- m_uniformBlockNames.clear();
- m_uniforms.clear();
- m_attributes.clear();
- m_uniformBlocks.clear();
m_status = QShaderProgram::NotReady;
+ m_log.clear();
+ m_dirty = false;
}
void Shader::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
@@ -146,300 +123,21 @@ void Shader::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
}
}
-void Shader::setGraphicsContext(GraphicsContext *context)
-{
- QMutexLocker lock(&m_mutex);
- m_graphicsContext = context;
- if (m_graphicsContext) {
- m_contextConnection = QObject::connect(m_graphicsContext->openGLContext(),
- &QOpenGLContext::aboutToBeDestroyed,
- [this] { setGraphicsContext(nullptr); });
- }
-}
-
-GraphicsContext *Shader::graphicsContext()
-{
- QMutexLocker lock(&m_mutex);
- return m_graphicsContext;
-}
-
-QVector<QString> Shader::uniformsNames() const
-{
- return m_uniformsNames;
-}
-
-QVector<QString> Shader::attributesNames() const
-{
- return m_attributesNames;
-}
-
-QVector<QString> Shader::uniformBlockNames() const
-{
- return m_uniformBlockNames;
-}
-
-QVector<QString> Shader::storageBlockNames() const
-{
- return m_shaderStorageBlockNames;
-}
-
-QVector<QByteArray> Shader::shaderCode() const
-{
- return m_shaderCode;
-}
-
void Shader::setShaderCode(QShaderProgram::ShaderType type, const QByteArray &code)
{
if (code == m_shaderCode[type])
return;
m_shaderCode[type] = code;
- m_isLoaded = false;
- m_status = QShaderProgram::NotReady;
- updateDNA();
m_requiresFrontendSync = true;
+ m_dirty = true;
+ setStatus(QShaderProgram::NotReady);
markDirty(AbstractRenderer::ShadersDirty);
}
-QHash<QString, ShaderUniform> Shader::activeUniformsForUniformBlock(int blockIndex) const
-{
- return m_uniformBlockIndexToShaderUniforms.value(blockIndex);
-}
-
-ShaderUniformBlock Shader::uniformBlockForBlockIndex(int blockIndex)
-{
- for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
- if (m_uniformBlocks[i].m_index == blockIndex) {
- return m_uniformBlocks[i];
- }
- }
- return ShaderUniformBlock();
-}
-
-ShaderUniformBlock Shader::uniformBlockForBlockNameId(int blockNameId)
-{
- for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
- if (m_uniformBlocks[i].m_nameId == blockNameId) {
- return m_uniformBlocks[i];
- }
- }
- return ShaderUniformBlock();
-}
-
-ShaderUniformBlock Shader::uniformBlockForBlockName(const QString &blockName)
-{
- for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) {
- if (m_uniformBlocks[i].m_name == blockName) {
- return m_uniformBlocks[i];
- }
- }
- return ShaderUniformBlock();
-}
-
-ShaderStorageBlock Shader::storageBlockForBlockIndex(int blockIndex)
-{
- for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
- if (m_shaderStorageBlocks[i].m_index == blockIndex)
- return m_shaderStorageBlocks[i];
- }
- return ShaderStorageBlock();
-}
-
-ShaderStorageBlock Shader::storageBlockForBlockNameId(int blockNameId)
-{
- for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
- if (m_shaderStorageBlocks[i].m_nameId == blockNameId)
- return m_shaderStorageBlocks[i];
- }
- return ShaderStorageBlock();
-}
-
-ShaderStorageBlock Shader::storageBlockForBlockName(const QString &blockName)
-{
- for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) {
- if (m_shaderStorageBlocks[i].m_name == blockName)
- return m_shaderStorageBlocks[i];
- }
- return ShaderStorageBlock();
-}
-
-void Shader::prepareUniforms(ShaderParameterPack &pack)
-{
- const PackUniformHash &values = pack.uniforms();
-
- auto it = values.keys.cbegin();
- const auto end = values.keys.cend();
-
- while (it != end) {
- // Find if there's a uniform with the same name id
- for (const ShaderUniform &uniform : qAsConst(m_uniforms)) {
- if (uniform.m_nameId == *it) {
- pack.setSubmissionUniform(uniform);
- break;
- }
- }
- ++it;
- }
-}
-
-void Shader::setFragOutputs(const QHash<QString, int> &fragOutputs)
-{
- {
- QMutexLocker lock(&m_mutex);
- m_fragOutputs = fragOutputs;
- }
- updateDNA();
-}
-
-const QHash<QString, int> Shader::fragOutputs() const
-{
- QMutexLocker lock(&m_mutex);
- return m_fragOutputs;
-}
-
-void Shader::updateDNA()
-{
- m_oldDna = m_dna;
- uint codeHash = qHash(m_shaderCode[QShaderProgram::Vertex]
- + m_shaderCode[QShaderProgram::TessellationControl]
- + m_shaderCode[QShaderProgram::TessellationEvaluation]
- + m_shaderCode[QShaderProgram::Geometry]
- + m_shaderCode[QShaderProgram::Fragment]
- + m_shaderCode[QShaderProgram::Compute]);
-
- QMutexLocker locker(&m_mutex);
- uint attachmentHash = 0;
- QHash<QString, int>::const_iterator it = m_fragOutputs.cbegin();
- QHash<QString, int>::const_iterator end = m_fragOutputs.cend();
- while (it != end) {
- attachmentHash += ::qHash(it.value()) + ::qHash(it.key());
- ++it;
- }
- const ProgramDNA newDNA = codeHash + attachmentHash;
-
- // Remove reference to shader based on DNA in the ShaderCache
- // In turn this will allow to purge the shader program if no other
- // Shader backend node references it
- // Note: the purge is actually happening occasionally in GraphicsContext::beginDrawing
- if (m_graphicsContext && newDNA != m_oldDna)
- m_graphicsContext->removeShaderProgramReference(this);
-
- m_dna = newDNA;
-}
-
-void Shader::initializeUniforms(const QVector<ShaderUniform> &uniformsDescription)
-{
- m_uniforms = uniformsDescription;
- m_uniformsNames.resize(uniformsDescription.size());
- m_uniformsNamesIds.reserve(uniformsDescription.size());
- m_standardUniformNamesIds.reserve(5);
- QHash<QString, ShaderUniform> activeUniformsInDefaultBlock;
-
- static const QVector<int> standardUniformNameIds = {
- modelMatrixNameId,
- viewMatrixNameId,
- projectionMatrixNameId,
- modelViewMatrixNameId,
- viewProjectionMatrixNameId,
- modelViewProjectionNameId,
- mvpNameId,
- inverseModelMatrixNameId,
- inverseViewMatrixNameId,
- inverseProjectionMatrixNameId,
- inverseModelViewNameId,
- inverseViewProjectionMatrixNameId,
- inverseModelViewProjectionNameId,
- modelNormalMatrixNameId,
- modelViewNormalNameId,
- viewportMatrixNameId,
- inverseViewportMatrixNameId,
- aspectRatioNameId,
- exposureNameId,
- gammaNameId,
- timeNameId,
- eyePositionNameId,
- skinningPaletteNameId,
- };
-
- for (int i = 0, m = uniformsDescription.size(); i < m; i++) {
- m_uniformsNames[i] = m_uniforms[i].m_name;
- const int nameId = StringToInt::lookupId(m_uniformsNames[i]);
- m_uniforms[i].m_nameId = nameId;
-
- // Is the uniform a Qt3D "Standard" uniform or a user defined one?
- if (standardUniformNameIds.contains(nameId))
- m_standardUniformNamesIds.push_back(nameId);
- else
- m_uniformsNamesIds.push_back(nameId);
-
- if (uniformsDescription[i].m_blockIndex == -1) { // Uniform is in default block
- qCDebug(Shaders) << "Active Uniform in Default Block " << uniformsDescription[i].m_name << uniformsDescription[i].m_blockIndex;
- activeUniformsInDefaultBlock.insert(uniformsDescription[i].m_name, uniformsDescription[i]);
- }
- }
- m_uniformBlockIndexToShaderUniforms.insert(-1, activeUniformsInDefaultBlock);
-}
-
-void Shader::initializeAttributes(const QVector<ShaderAttribute> &attributesDescription)
-{
- m_attributes = attributesDescription;
- m_attributesNames.resize(attributesDescription.size());
- m_attributeNamesIds.resize(attributesDescription.size());
- for (int i = 0, m = attributesDescription.size(); i < m; i++) {
- m_attributesNames[i] = attributesDescription[i].m_name;
- m_attributes[i].m_nameId = StringToInt::lookupId(m_attributesNames[i]);
- m_attributeNamesIds[i] = m_attributes[i].m_nameId;
- qCDebug(Shaders) << "Active Attribute " << attributesDescription[i].m_name;
- }
-}
-
-void Shader::initializeUniformBlocks(const QVector<ShaderUniformBlock> &uniformBlockDescription)
-{
- m_uniformBlocks = uniformBlockDescription;
- m_uniformBlockNames.resize(uniformBlockDescription.size());
- m_uniformBlockNamesIds.resize(uniformBlockDescription.size());
- for (int i = 0, m = uniformBlockDescription.size(); i < m; ++i) {
- m_uniformBlockNames[i] = m_uniformBlocks[i].m_name;
- m_uniformBlockNamesIds[i] = StringToInt::lookupId(m_uniformBlockNames[i]);
- m_uniformBlocks[i].m_nameId = m_uniformBlockNamesIds[i];
- qCDebug(Shaders) << "Initializing Uniform Block {" << m_uniformBlockNames[i] << "}";
-
- // Find all active uniforms for the shader block
- QVector<ShaderUniform>::const_iterator uniformsIt = m_uniforms.cbegin();
- const QVector<ShaderUniform>::const_iterator uniformsEnd = m_uniforms.cend();
-
- QVector<QString>::const_iterator uniformNamesIt = m_uniformsNames.cbegin();
- const QVector<QString>::const_iterator uniformNamesEnd = m_attributesNames.cend();
-
- QHash<QString, ShaderUniform> activeUniformsInBlock;
-
- while (uniformsIt != uniformsEnd && uniformNamesIt != uniformNamesEnd) {
- if (uniformsIt->m_blockIndex == uniformBlockDescription[i].m_index) {
- QString uniformName = *uniformNamesIt;
- if (!m_uniformBlockNames[i].isEmpty() && !uniformName.startsWith(m_uniformBlockNames[i]))
- uniformName = m_uniformBlockNames[i] + QLatin1Char('.') + *uniformNamesIt;
- activeUniformsInBlock.insert(uniformName, *uniformsIt);
- qCDebug(Shaders) << "Active Uniform Block " << uniformName << " in block " << m_uniformBlockNames[i] << " at index " << uniformsIt->m_blockIndex;
- }
- ++uniformsIt;
- ++uniformNamesIt;
- }
- m_uniformBlockIndexToShaderUniforms.insert(uniformBlockDescription[i].m_index, activeUniformsInBlock);
- }
-}
-
-void Shader::initializeShaderStorageBlocks(const QVector<ShaderStorageBlock> &shaderStorageBlockDescription)
+QVector<QByteArray> Shader::shaderCode() const
{
- m_shaderStorageBlocks = shaderStorageBlockDescription;
- m_shaderStorageBlockNames.resize(shaderStorageBlockDescription.size());
- m_shaderStorageBlockNamesIds.resize(shaderStorageBlockDescription.size());
-
- for (int i = 0, m = shaderStorageBlockDescription.size(); i < m; ++i) {
- m_shaderStorageBlockNames[i] = m_shaderStorageBlocks[i].m_name;
- m_shaderStorageBlockNamesIds[i] = StringToInt::lookupId(m_shaderStorageBlockNames[i]);
- m_shaderStorageBlocks[i].m_nameId =m_shaderStorageBlockNamesIds[i];
- qCDebug(Shaders) << "Initializing Shader Storage Block {" << m_shaderStorageBlockNames[i] << "}";
- }
+ return m_shaderCode;
}
/*!
@@ -449,26 +147,11 @@ void Shader::initializeShaderStorageBlocks(const QVector<ShaderStorageBlock> &sh
*/
void Shader::initializeFromReference(const Shader &other)
{
- Q_ASSERT(m_dna == other.m_dna);
- m_uniformsNamesIds = other.m_uniformsNamesIds;
- m_standardUniformNamesIds = other.m_standardUniformNamesIds;
- m_uniformsNames = other.m_uniformsNames;
- m_uniforms = other.m_uniforms;
- m_attributesNames = other.m_attributesNames;
- m_attributeNamesIds = other.m_attributeNamesIds;
- m_attributes = other.m_attributes;
- m_uniformBlockNamesIds = other.m_uniformBlockNamesIds;
- m_uniformBlockNames = other.m_uniformBlockNames;
- m_uniformBlocks = other.m_uniformBlocks;
- m_uniformBlockIndexToShaderUniforms = other.m_uniformBlockIndexToShaderUniforms;
- m_fragOutputs = other.m_fragOutputs;
- m_shaderStorageBlockNamesIds = other.m_shaderStorageBlockNamesIds;
- m_shaderStorageBlockNames = other.m_shaderStorageBlockNames;
- m_shaderStorageBlocks = other.m_shaderStorageBlocks;
- m_isLoaded = other.m_isLoaded;
m_status = other.m_status;
m_log = other.m_log;
m_requiresFrontendSync = true;
+ setStatus(other.status());
+ setLog(other.log());
}
void Shader::setLog(const QString &log)
@@ -483,6 +166,32 @@ void Shader::setStatus(QShaderProgram::Status status)
m_requiresFrontendSync = true;
}
+ShaderFunctor::ShaderFunctor(AbstractRenderer *renderer, ShaderManager *manager)
+ : m_renderer(renderer)
+ , m_shaderManager(manager)
+{
+}
+
+QBackendNode *ShaderFunctor::create(const QNodeCreatedChangeBasePtr &change) const
+{
+ Shader *backend = m_shaderManager->getOrCreateResource(change->subjectId());
+ backend->setRenderer(m_renderer);
+ return backend;
+}
+
+QBackendNode *ShaderFunctor::get(QNodeId id) const
+{
+ return m_shaderManager->lookupResource(id);
+}
+
+void ShaderFunctor::destroy(QNodeId id) const
+{
+ m_shaderManager->addShaderIdToCleanup(id);
+ // We only add ourselves to the dirty list
+ // The actual removal needs to be performed after we have
+ // destroyed the associated APIShader in the RenderThread
+}
+
} // namespace Render
} // namespace Qt3DRender