1 | // Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB). |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QT3DRENDER_RENDER_RHI_SHADERPARAMETERPACK_P_H |
5 | #define QT3DRENDER_RENDER_RHI_SHADERPARAMETERPACK_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists for the convenience |
12 | // of other Qt classes. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QVariant> |
19 | #include <QByteArray> |
20 | #include <vector> |
21 | #include <QOpenGLShaderProgram> |
22 | #include <Qt3DCore/qnodeid.h> |
23 | #include <Qt3DRender/private/renderlogging_p.h> |
24 | #include <Qt3DRender/private/uniform_p.h> |
25 | #include <shadervariables_p.h> |
26 | |
27 | QT_BEGIN_NAMESPACE |
28 | |
29 | class QOpenGLShaderProgram; |
30 | |
31 | namespace Qt3DRender { |
32 | namespace Render { |
33 | namespace Rhi { |
34 | |
35 | class GraphicsContext; |
36 | |
37 | struct BlockToUBO |
38 | { |
39 | int m_blockIndex; |
40 | int m_bindingIndex; |
41 | Qt3DCore::QNodeId m_bufferID; |
42 | bool m_needsUpdate; |
43 | QHash<QString, QVariant> m_updatedProperties; |
44 | }; |
45 | QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, Rhi, BlockToUBO, Q_RELOCATABLE_TYPE) |
46 | |
47 | struct BlockToSSBO |
48 | { |
49 | int m_blockIndex; |
50 | int m_bindingIndex; |
51 | Qt3DCore::QNodeId m_bufferID; |
52 | }; |
53 | QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, Rhi, BlockToSSBO, Q_PRIMITIVE_TYPE) |
54 | |
55 | struct ShaderDataForUBO |
56 | { |
57 | int m_bindingIndex; |
58 | Qt3DCore::QNodeId m_shaderDataID; |
59 | }; |
60 | QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, Rhi, ShaderDataForUBO, Q_PRIMITIVE_TYPE) |
61 | |
62 | bool operator==(const ShaderDataForUBO &a, const ShaderDataForUBO &b); |
63 | |
64 | struct PackUniformHash |
65 | { |
66 | std::vector<int> keys; |
67 | std::vector<UniformValue> values; |
68 | |
69 | PackUniformHash() |
70 | { |
71 | } |
72 | |
73 | void reserve(int count) |
74 | { |
75 | keys.reserve(n: count); |
76 | values.reserve(n: count); |
77 | } |
78 | |
79 | inline int indexForKey(int key) const |
80 | { |
81 | const auto b = keys.cbegin(); |
82 | const auto e = keys.cend(); |
83 | const auto it = std::find(first: b, last: e, val: key); |
84 | if (it == e) |
85 | return -1; |
86 | return std::distance(first: b, last: it); |
87 | } |
88 | |
89 | void insert(int key, const UniformValue &value) |
90 | { |
91 | const int idx = indexForKey(key); |
92 | if (idx != -1) { |
93 | values[idx] = value; |
94 | } else { |
95 | keys.push_back(x: key); |
96 | values.push_back(x: value); |
97 | } |
98 | } |
99 | |
100 | void insert(int key, UniformValue &&value) |
101 | { |
102 | const int idx = indexForKey(key); |
103 | if (idx != -1) { |
104 | values[idx] = std::move(value); |
105 | } else { |
106 | keys.push_back(x: key); |
107 | values.push_back(x: std::move(value)); |
108 | } |
109 | } |
110 | |
111 | const UniformValue &value(int key) const |
112 | { |
113 | const int idx = indexForKey(key); |
114 | return values[idx]; |
115 | } |
116 | |
117 | UniformValue &value(int key) |
118 | { |
119 | const int idx = indexForKey(key); |
120 | if (idx != -1) |
121 | return values[idx]; |
122 | insert(key, value: UniformValue()); |
123 | return value(key); |
124 | } |
125 | |
126 | template<typename F> |
127 | void apply(int key, F func) const noexcept |
128 | { |
129 | const int idx = indexForKey(key); |
130 | if (idx != -1) |
131 | func(values[idx]); |
132 | } |
133 | |
134 | void erase(int idx) |
135 | { |
136 | keys.erase(position: keys.begin() + idx); |
137 | values.erase(position: values.begin() + idx); |
138 | } |
139 | |
140 | bool contains(int key) const noexcept |
141 | { |
142 | const auto b = keys.cbegin(); |
143 | const auto e = keys.cend(); |
144 | return std::find(first: b, last: e, val: key) != e; |
145 | } |
146 | }; |
147 | |
148 | class Q_AUTOTEST_EXPORT ShaderParameterPack |
149 | { |
150 | public: |
151 | ~ShaderParameterPack(); |
152 | |
153 | void reserve(int uniformCount); |
154 | void setUniform(const int glslNameId, const UniformValue &val); |
155 | void setTexture(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id); |
156 | void setImage(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id); |
157 | |
158 | void setUniformBuffer(BlockToUBO blockToUBO); |
159 | void setShaderStorageBuffer(BlockToSSBO blockToSSBO); |
160 | void setShaderDataForUBO(ShaderDataForUBO shaderDataForUBO); |
161 | void setSubmissionUniformIndex(const int shaderUniformIndex); |
162 | |
163 | inline PackUniformHash &uniforms() { return m_uniforms; } |
164 | inline const PackUniformHash &uniforms() const { return m_uniforms; } |
165 | UniformValue uniform(const int glslNameId) const { return m_uniforms.value(key: glslNameId); } |
166 | |
167 | |
168 | struct NamedResource |
169 | { |
170 | enum Type { |
171 | Texture = 0, |
172 | Image |
173 | }; |
174 | |
175 | NamedResource() {} |
176 | NamedResource(const int glslNameId, Qt3DCore::QNodeId texId, |
177 | int uniformArrayIndex, Type type) |
178 | : glslNameId(glslNameId) |
179 | , nodeId(texId) |
180 | , uniformArrayIndex(uniformArrayIndex) |
181 | , type(type) |
182 | { } |
183 | |
184 | int glslNameId; |
185 | Qt3DCore::QNodeId nodeId; |
186 | int uniformArrayIndex; |
187 | Type type; |
188 | |
189 | bool operator==(const NamedResource &other) const |
190 | { |
191 | return glslNameId == other.glslNameId && |
192 | nodeId == other.nodeId && |
193 | uniformArrayIndex == other.uniformArrayIndex && |
194 | type == other.type; |
195 | } |
196 | |
197 | bool operator!=(const NamedResource &other) const |
198 | { |
199 | return !(*this == other); |
200 | } |
201 | }; |
202 | |
203 | inline const std::vector<NamedResource> &textures() const { return m_textures; } |
204 | inline const std::vector<NamedResource> &images() const { return m_images; } |
205 | inline const std::vector<BlockToUBO> &uniformBuffers() const { return m_uniformBuffers; } |
206 | inline const std::vector<BlockToSSBO> &shaderStorageBuffers() const { return m_shaderStorageBuffers; } |
207 | inline const std::vector<int> &submissionUniformIndices() const { return m_submissionUniformIndices; } |
208 | inline const std::vector<ShaderDataForUBO> &shaderDatasForUBOs() const { return m_shaderDatasForUBOs; } |
209 | private: |
210 | PackUniformHash m_uniforms; |
211 | |
212 | std::vector<NamedResource> m_textures; |
213 | std::vector<NamedResource> m_images; |
214 | std::vector<BlockToUBO> m_uniformBuffers; |
215 | std::vector<BlockToSSBO> m_shaderStorageBuffers; |
216 | std::vector<int> m_submissionUniformIndices; |
217 | std::vector<ShaderDataForUBO> m_shaderDatasForUBOs; |
218 | |
219 | friend class RenderView; |
220 | }; |
221 | QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, Rhi, ShaderParameterPack::NamedResource, Q_PRIMITIVE_TYPE) |
222 | |
223 | } // namespace Rhi |
224 | } // namespace Render |
225 | } // namespace Qt3DRender |
226 | |
227 | QT_END_NAMESPACE |
228 | |
229 | Q_DECLARE_METATYPE(Qt3DRender::Render::Rhi::ShaderParameterPack) |
230 | |
231 | #endif // QT3DRENDER_RENDER_RHI_SHADERPARAMETERPACK_P_H |
232 | |