summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2020-11-27 10:53:06 +0100
committerPaul Lemire <paul.lemire@kdab.com>2020-11-28 10:13:23 +0100
commitcf6b181227b02b23050198d21c54bd03eacd3b55 (patch)
tree50b70657d76b0a110aec49af6710a85c1c48213d
parent6fac2818ac283c1db0af51a5d8c556fa8afc61ae (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.cpp30
-rw-r--r--src/render/backend/uniform.cpp4
-rw-r--r--src/render/backend/uniform_p.h4
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<>