Shader: record standard uniform at loading time

Avoids having to check for each uniform (for each frame, each geometry)
whether it is a standard uniform or a user defined one.

Change-Id: I76cff7869aacc1343a9acf991f8035b8118581ed
Reviewed-by: Mike Krus <mike.krus@kdab.com>
This commit is contained in:
Paul Lemire 2019-09-27 07:16:58 +02:00
parent 9a417bcb92
commit 3019497559
5 changed files with 140 additions and 45 deletions

View File

@ -50,10 +50,19 @@ namespace Render {
namespace {
struct StringToIntCache
{
QReadWriteLock lock;
QHash<QString, int> map = QHash<QString, int>();
QVector<QString> reverseMap = QVector<QString>();
static StringToIntCache& instance()
{
static StringToIntCache c;
return c;
}
};
} // anonymous
int StringToInt::lookupId(QLatin1String str)
@ -64,20 +73,21 @@ int StringToInt::lookupId(QLatin1String str)
int StringToInt::lookupId(const QString &str)
{
auto& cache = StringToIntCache::instance();
int idx;
{
QReadLocker readLocker(&lock);
idx = map.value(str, -1);
QReadLocker readLocker(&cache.lock);
idx = cache.map.value(str, -1);
}
if (Q_UNLIKELY(idx < 0)) {
QWriteLocker writeLocker(&lock);
idx = map.value(str, -1);
QWriteLocker writeLocker(&cache.lock);
idx = cache.map.value(str, -1);
if (idx < 0) {
idx = reverseMap.size();
Q_ASSERT(map.size() == reverseMap.size());
map.insert(str, idx);
reverseMap.append(str);
idx = cache.reverseMap.size();
Q_ASSERT(cache.map.size() == cache.reverseMap.size());
cache.map.insert(str, idx);
cache.reverseMap.append(str);
}
}
return idx;
@ -85,9 +95,10 @@ int StringToInt::lookupId(const QString &str)
QString StringToInt::lookupString(int idx)
{
QReadLocker readLocker(&lock);
if (Q_LIKELY(reverseMap.size() > idx))
return reverseMap.at(idx);
auto& cache = StringToIntCache::instance();
QReadLocker readLocker(&cache.lock);
if (Q_LIKELY(cache.reverseMap.size() > idx))
return cache.reverseMap.at(idx);
return QString();
}

View File

@ -57,6 +57,29 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
const int Shader::modelMatrixNameId = StringToInt::lookupId(QLatin1String("modelMatrix"));
const int Shader::viewMatrixNameId = StringToInt::lookupId(QLatin1String("viewMatrix"));
const int Shader::projectionMatrixNameId = StringToInt::lookupId(QLatin1String("projectionMatrix"));
const int Shader::modelViewMatrixNameId = StringToInt::lookupId(QLatin1String("modelView"));
const int Shader::viewProjectionMatrixNameId = StringToInt::lookupId(QLatin1String("viewProjectionMatrix"));
const int Shader::modelViewProjectionNameId = StringToInt::lookupId(QLatin1String("modelViewProjection"));
const int Shader::mvpNameId = StringToInt::lookupId(QLatin1String("mvp"));
const int Shader::inverseModelMatrixNameId = StringToInt::lookupId(QLatin1String("inverseModelMatrix"));
const int Shader::inverseViewMatrixNameId = StringToInt::lookupId(QLatin1String("inverseViewMatrix"));
const int Shader::inverseProjectionMatrixNameId = StringToInt::lookupId(QLatin1String("inverseProjectionMatrix"));
const int Shader::inverseModelViewNameId = StringToInt::lookupId(QLatin1String("inverseModelView"));
const int Shader::inverseViewProjectionMatrixNameId = StringToInt::lookupId(QLatin1String("inverseViewProjectionMatrix"));
const int Shader::inverseModelViewProjectionNameId = StringToInt::lookupId(QLatin1String("inverseModelViewProjection"));
const int Shader::modelNormalMatrixNameId = StringToInt::lookupId(QLatin1String("modelNormalMatrix"));
const int Shader::modelViewNormalNameId = StringToInt::lookupId(QLatin1String("modelViewNormal"));
const int Shader::viewportMatrixNameId = StringToInt::lookupId(QLatin1String("viewportMatrix"));
const int Shader::inverseViewportMatrixNameId = StringToInt::lookupId(QLatin1String("inverseViewportMatrix"));
const int Shader::aspectRatioNameId = StringToInt::lookupId(QLatin1String("aspectRatio"));
const int Shader::exposureNameId = StringToInt::lookupId(QLatin1String("exposure"));
const int Shader::gammaNameId = StringToInt::lookupId(QLatin1String("gamma"));
const int Shader::timeNameId = StringToInt::lookupId(QLatin1String("time"));
const int Shader::eyePositionNameId = StringToInt::lookupId(QLatin1String("eyePosition"));
const int Shader::skinningPaletteNameId = StringToInt::lookupId(QLatin1String("skinningPalette[0]"));
Shader::Shader()
: BackendNode(ReadWrite)
@ -308,13 +331,47 @@ void Shader::initializeUniforms(const QVector<ShaderUniform> &uniformsDescriptio
{
m_uniforms = uniformsDescription;
m_uniformsNames.resize(uniformsDescription.size());
m_uniformsNamesIds.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;
m_uniforms[i].m_nameId = StringToInt::lookupId(m_uniformsNames[i]);
m_uniformsNamesIds[i] = m_uniforms[i].m_nameId;
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]);
@ -394,6 +451,7 @@ 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;

View File

@ -75,6 +75,30 @@ typedef uint ProgramDNA;
class Q_AUTOTEST_EXPORT Shader : public BackendNode
{
public:
static const int modelMatrixNameId;
static const int viewMatrixNameId;
static const int projectionMatrixNameId;
static const int modelViewMatrixNameId;
static const int viewProjectionMatrixNameId;
static const int modelViewProjectionNameId;
static const int mvpNameId;
static const int inverseModelMatrixNameId;
static const int inverseViewMatrixNameId;
static const int inverseProjectionMatrixNameId;
static const int inverseModelViewNameId;
static const int inverseViewProjectionMatrixNameId;
static const int inverseModelViewProjectionNameId;
static const int modelNormalMatrixNameId;
static const int modelViewNormalNameId;
static const int viewportMatrixNameId;
static const int inverseViewportMatrixNameId;
static const int aspectRatioNameId;
static const int exposureNameId;
static const int gammaNameId;
static const int timeNameId;
static const int eyePositionNameId;
static const int skinningPaletteNameId;
Shader();
~Shader();
@ -88,6 +112,7 @@ public:
const QHash<QString, int> fragOutputs() const;
inline QVector<int> uniformsNamesIds() const { return m_uniformsNamesIds; }
inline QVector<int> standardUniformNameIds() const { return m_standardUniformNamesIds; }
inline QVector<int> uniformBlockNamesIds() const { return m_uniformBlockNamesIds; }
inline QVector<int> storageBlockNamesIds() const { return m_shaderStorageBlockNamesIds; }
inline QVector<int> attributeNamesIds() const { return m_attributeNamesIds; }
@ -128,6 +153,7 @@ public:
private:
QVector<QString> m_uniformsNames;
QVector<int> m_uniformsNamesIds;
QVector<int> m_standardUniformNamesIds;
QVector<ShaderUniform> m_uniforms;
QVector<QString> m_attributesNames;

View File

@ -119,29 +119,29 @@ RenderView::StandardUniformsNameToTypeHash RenderView::initializeStandardUniform
{
RenderView::StandardUniformsNameToTypeHash setters;
setters.insert(StringToInt::lookupId(QLatin1String("modelMatrix")), ModelMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("viewMatrix")), ViewMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("projectionMatrix")), ProjectionMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("modelView")), ModelViewMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("viewProjectionMatrix")), ViewProjectionMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("modelViewProjection")), ModelViewProjectionMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("mvp")), ModelViewProjectionMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("inverseModelMatrix")), InverseModelMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("inverseViewMatrix")), InverseViewMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("inverseProjectionMatrix")), InverseProjectionMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("inverseModelView")), InverseModelViewMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("inverseViewProjectionMatrix")), InverseViewProjectionMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("inverseModelViewProjection")), InverseModelViewProjectionMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("modelNormalMatrix")), ModelNormalMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("modelViewNormal")), ModelViewNormalMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("viewportMatrix")), ViewportMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("inverseViewportMatrix")), InverseViewportMatrix);
setters.insert(StringToInt::lookupId(QLatin1String("aspectRatio")), AspectRatio);
setters.insert(StringToInt::lookupId(QLatin1String("exposure")), Exposure);
setters.insert(StringToInt::lookupId(QLatin1String("gamma")), Gamma);
setters.insert(StringToInt::lookupId(QLatin1String("time")), Time);
setters.insert(StringToInt::lookupId(QLatin1String("eyePosition")), EyePosition);
setters.insert(StringToInt::lookupId(QLatin1String("skinningPalette[0]")), SkinningPalette);
setters.insert(Shader::modelMatrixNameId, ModelMatrix);
setters.insert(Shader::viewMatrixNameId, ViewMatrix);
setters.insert(Shader::projectionMatrixNameId, ProjectionMatrix);
setters.insert(Shader::modelViewMatrixNameId, ModelViewMatrix);
setters.insert(Shader::viewProjectionMatrixNameId, ViewProjectionMatrix);
setters.insert(Shader::modelViewProjectionNameId, ModelViewProjectionMatrix);
setters.insert(Shader::mvpNameId, ModelViewProjectionMatrix);
setters.insert(Shader::inverseModelMatrixNameId, InverseModelMatrix);
setters.insert(Shader::inverseViewMatrixNameId, InverseViewMatrix);
setters.insert(Shader::inverseProjectionMatrixNameId, InverseProjectionMatrix);
setters.insert(Shader::inverseModelViewNameId, InverseModelViewMatrix);
setters.insert(Shader::inverseViewProjectionMatrixNameId, InverseViewProjectionMatrix);
setters.insert(Shader::inverseModelViewProjectionNameId, InverseModelViewProjectionMatrix);
setters.insert(Shader::modelNormalMatrixNameId, ModelNormalMatrix);
setters.insert(Shader::modelViewNormalNameId, ModelViewNormalMatrix);
setters.insert(Shader::viewportMatrixNameId, ViewportMatrix);
setters.insert(Shader::inverseViewportMatrixNameId, InverseViewportMatrix);
setters.insert(Shader::aspectRatioNameId, AspectRatio);
setters.insert(Shader::exposureNameId, Exposure);
setters.insert(Shader::gammaNameId, Gamma);
setters.insert(Shader::timeNameId, Time);
setters.insert(Shader::eyePositionNameId, EyePosition);
setters.insert(Shader::skinningPaletteNameId, SkinningPalette);
return setters;
}
@ -1023,6 +1023,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
// If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name
// equals to the parameter name
const QVector<int> uniformNamesIds = shader->uniformsNamesIds();
const QVector<int> standardUniformNamesIds = shader->standardUniformNameIds();
const QVector<int> uniformBlockNamesIds = shader->uniformBlockNamesIds();
const QVector<int> shaderStorageBlockNamesIds = shader->storageBlockNamesIds();
const QVector<int> attributeNamesIds = shader->attributeNamesIds();
@ -1042,16 +1043,15 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
shader->setFragOutputs(fragOutputs);
}
if (!uniformNamesIds.isEmpty() || !attributeNamesIds.isEmpty() ||
if (!uniformNamesIds.isEmpty() || !standardUniformNamesIds.isEmpty() ||
!attributeNamesIds.isEmpty() ||
!shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) {
// Set default standard uniforms without bindings
const Matrix4x4 worldTransform = *(entity->worldTransform());
for (const int uniformNameId : uniformNamesIds) {
if (ms_standardUniformSetters.contains(uniformNameId))
for (const int uniformNameId : standardUniformNamesIds)
setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform);
}
// Set default attributes
command->m_activeAttributes = attributeNamesIds;

View File

@ -168,7 +168,7 @@ private Q_SLOTS:
engine.setRootEntity(entity);
QEventLoop eventLoop;
QTimer::singleShot(100, &eventLoop, SLOT(quit()));
QTimer::singleShot(1000, &eventLoop, SLOT(quit()));
eventLoop.exec();
// THEN