diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2020-11-27 10:53:06 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2020-11-28 10:13:23 +0100 |
commit | cf6b181227b02b23050198d21c54bd03eacd3b55 (patch) | |
tree | 50b70657d76b0a110aec49af6710a85c1c48213d | |
parent | 6fac2818ac283c1db0af51a5d8c556fa8afc61ae (diff) |
RHI: handle uniforms of type arrays properly
We weren't handling the possible array stride for uniform arrays.
For a float[8], the GPU might expect each float to fit in a vec4 slot.
We therefore have to handle that when uploading the values otherwise
we could end having data in what the GPU believe is padding data.
This required modifying the UniformValue object to report the number
of elements it contains as it might not necessarely be the same as the
array dimension reported by the shader introspection.
Note: it seems that the arrayStride might not be reported properly.
To work around that, if we know we are dealing with an array, we
compute the stride ourselves.
Pick-to: 6.0
Change-Id: I12b5379927dd47be888a40db58c2e5aba6e0730b
Reviewed-by: Mike Krus <mike.krus@kdab.com>
-rw-r--r-- | src/plugins/renderers/rhi/renderer/pipelineuboset.cpp | 30 | ||||
-rw-r--r-- | src/render/backend/uniform.cpp | 4 | ||||
-rw-r--r-- | src/render/backend/uniform_p.h | 4 |
3 files changed, 37 insertions, 1 deletions
diff --git a/src/plugins/renderers/rhi/renderer/pipelineuboset.cpp b/src/plugins/renderers/rhi/renderer/pipelineuboset.cpp index 0031d927d..0578c6a09 100644 --- a/src/plugins/renderers/rhi/renderer/pipelineuboset.cpp +++ b/src/plugins/renderers/rhi/renderer/pipelineuboset.cpp @@ -444,6 +444,33 @@ QByteArray rawDataForUniformValue(const QShaderDescription::BlockVariable &block ? QByteArray(value.constData<char>(), std::min(value.byteSize(), blockVariable.size)) : QByteArray::fromRawData(value.constData<char>(), std::min(value.byteSize(), blockVariable.size)); const int matrixStride = blockVariable.matrixStride; + int arrayStride = blockVariable.arrayStride; + const int firstArrayDim = !blockVariable.arrayDims.empty() ? blockVariable.arrayDims.first() : 0; + + if (blockVariable.arrayDims.size() > 1) + qCWarning(Backend) << "Multi Dimension arrays not handled yet"; + + if (arrayStride != 0 && matrixStride != 0) + qCWarning(Backend) << "Arrays of matrices not handled yet"; + + // Special cases for arrays + if (firstArrayDim > 0) { + // It appears that for a float myArray[8]; stride is reported as being + // 0 but expected size 128 bytes which means 16 bytes per float + // In that case we compute the arrayStride ourselves + if (arrayStride == 0) + arrayStride = blockVariable.size / firstArrayDim; + if (arrayStride != 0) { + QByteArray newRawData(firstArrayDim * arrayStride, '\0'); + const int byteSizePerEntry = value.elementByteSize(); + for (int i = 0, m = std::min(firstArrayDim, value.elementCount()); i < m; ++i) { + std::memcpy(newRawData.data() + i * arrayStride, + rawData.constData() + i * byteSizePerEntry, + byteSizePerEntry); + } + return newRawData; + } + } // Special cases for matrices which might have to be aligned to a vec4 stride if (matrixStride != 0 && value.byteSize() % matrixStride != 0) { @@ -457,6 +484,9 @@ QByteArray rawDataForUniformValue(const QShaderDescription::BlockVariable &block } return newRawData; } + + // Note: we currently don't handle array of matrices + return rawData; } diff --git a/src/render/backend/uniform.cpp b/src/render/backend/uniform.cpp index 12b496161..92fb077f7 100644 --- a/src/render/backend/uniform.cpp +++ b/src/render/backend/uniform.cpp @@ -239,7 +239,9 @@ UniformValue UniformValue::fromVariant(const QVariant &variant) if (listEntryType == qNodeIdTypeId) v.m_valueType = NodeId; - const int stride = byteSizeForMetaType(listEntryType) / sizeof(float); + v.m_elementByteSize = byteSizeForMetaType(listEntryType); + const int stride = v.m_elementByteSize / sizeof(float); + // Resize v.m_data v.m_data.resize(stride * variants.size()); diff --git a/src/render/backend/uniform_p.h b/src/render/backend/uniform_p.h index ee83823aa..b1ddcf01c 100644 --- a/src/render/backend/uniform_p.h +++ b/src/render/backend/uniform_p.h @@ -195,6 +195,7 @@ public: template<typename T> void setData(const QList<T> &v) { + m_elementByteSize = sizeof(T); m_data.resize(v.size() * sizeof(T) / sizeof(float)); m_valueType = ScalarValue; float *data = m_data.data(); @@ -204,6 +205,8 @@ public: static UniformValue fromVariant(const QVariant &variant); int byteSize() const { return int(m_data.size()) * sizeof(float); } + int elementCount() const { return byteSize() / elementByteSize(); } + int elementByteSize() const { return m_elementByteSize; } template<typename T> const T *constData() const @@ -235,6 +238,7 @@ private: // TODO: Replace this hack see QTBUG-57510 UniformType m_storedType = Unknown; + int m_elementByteSize = sizeof(float); }; template<> |