13 #ifndef hifi_render_ShapePipeline_h
14 #define hifi_render_ShapePipeline_h
16 #include <unordered_set>
18 #include <gpu/Batch.h>
19 #include <graphics/Material.h>
57 NUM_NON_CUSTOM = INVALID,
59 CUSTOM_MASK = (0xFF << CUSTOM_0),
62 using Flags = std::bitset<NUM_FLAGS>;
66 ShapeKey() : _flags{ 0 } {}
67 ShapeKey(
const Flags& flags) : _flags{flags} {}
69 friend ShapeKey operator&(
const ShapeKey& _Left,
const ShapeKey& _Right) {
return ShapeKey(_Left._flags & _Right._flags); }
70 friend ShapeKey operator|(
const ShapeKey& _Left,
const ShapeKey& _Right) {
return ShapeKey(_Left._flags | _Right._flags); }
71 friend ShapeKey operator^(
const ShapeKey& _Left,
const ShapeKey& _Right) {
return ShapeKey(_Left._flags ^ _Right._flags); }
76 Builder(ShapeKey key) : _flags{key._flags} {}
78 ShapeKey build()
const {
return ShapeKey{_flags}; }
80 Builder& withMaterial() { _flags.set(MATERIAL);
return (*
this); }
81 Builder& withTranslucent() { _flags.set(TRANSLUCENT);
return (*
this); }
82 Builder& withLightMap() { _flags.set(LIGHTMAP);
return (*
this); }
83 Builder& withTangents() { _flags.set(TANGENTS);
return (*
this); }
84 Builder& withUnlit() { _flags.set(UNLIT);
return (*
this); }
85 Builder& withDeformed() { _flags.set(DEFORMED);
return (*
this); }
86 Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED);
return (*
this); }
87 Builder& withDepthBias() { _flags.set(DEPTH_BIAS);
return (*
this); }
88 Builder& withWireframe() { _flags.set(WIREFRAME);
return (*
this); }
89 Builder& withFade() { _flags.set(FADE);
return (*
this); }
90 Builder& withMToon() { _flags.set(MTOON);
return (*
this); }
92 Builder& withoutCullFace() {
return withCullFaceMode(graphics::MaterialKey::CullFaceMode::CULL_NONE); }
93 Builder& withCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) {
94 switch (cullFaceMode) {
95 case graphics::MaterialKey::CullFaceMode::CULL_NONE:
96 _flags.set(CULL_FACE_NONE);
97 _flags.reset(CULL_FACE_FRONT);
99 case graphics::MaterialKey::CullFaceMode::CULL_FRONT:
100 _flags.reset(CULL_FACE_NONE);
101 _flags.set(CULL_FACE_FRONT);
103 case graphics::MaterialKey::CullFaceMode::CULL_BACK:
104 _flags.reset(CULL_FACE_NONE);
105 _flags.reset(CULL_FACE_FRONT);
113 Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE);
return (*
this); }
114 Builder& invalidate() { _flags.set(INVALID);
return (*
this); }
116 Builder& withCustom(uint8_t custom) { _flags &= (~CUSTOM_MASK); _flags |= (custom << CUSTOM_0);
return (*
this); }
118 static const ShapeKey ownPipeline() {
return Builder().withOwnPipeline(); }
119 static const ShapeKey invalid() {
return Builder().invalidate(); }
122 friend class ShapeKey;
125 ShapeKey(
const Builder& builder) : ShapeKey{builder._flags} {}
129 Filter(Flags flags, Flags mask) : _flags{flags}, _mask{mask} {}
130 Filter(
const ShapeKey& key) : _flags{ key._flags } { _mask.set(); }
137 Filter build()
const {
return Filter(_flags, _mask); }
139 Builder& withMaterial() { _flags.set(MATERIAL); _mask.set(MATERIAL);
return (*
this); }
140 Builder& withoutMaterial() { _flags.reset(MATERIAL); _mask.set(MATERIAL);
return (*
this); }
142 Builder& withTranslucent() { _flags.set(TRANSLUCENT); _mask.set(TRANSLUCENT);
return (*
this); }
143 Builder& withOpaque() { _flags.reset(TRANSLUCENT); _mask.set(TRANSLUCENT);
return (*
this); }
145 Builder& withLightMap() { _flags.set(LIGHTMAP); _mask.set(LIGHTMAP);
return (*
this); }
146 Builder& withoutLightMap() { _flags.reset(LIGHTMAP); _mask.set(LIGHTMAP);
return (*
this); }
148 Builder& withTangents() { _flags.set(TANGENTS); _mask.set(TANGENTS);
return (*
this); }
149 Builder& withoutTangents() { _flags.reset(TANGENTS); _mask.set(TANGENTS);
return (*
this); }
151 Builder& withUnlit() { _flags.set(UNLIT); _mask.set(UNLIT);
return (*
this); }
152 Builder& withoutUnlit() { _flags.reset(UNLIT); _mask.set(UNLIT);
return (*
this); }
154 Builder& withDeformed() { _flags.set(DEFORMED); _mask.set(DEFORMED);
return (*
this); }
155 Builder& withoutDeformed() { _flags.reset(DEFORMED); _mask.set(DEFORMED);
return (*
this); }
157 Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); _mask.set(DUAL_QUAT_SKINNED);
return (*
this); }
158 Builder& withoutDualQuatSkinned() { _flags.reset(DUAL_QUAT_SKINNED); _mask.set(DUAL_QUAT_SKINNED);
return (*
this); }
160 Builder& withDepthBias() { _flags.set(DEPTH_BIAS); _mask.set(DEPTH_BIAS);
return (*
this); }
161 Builder& withoutDepthBias() { _flags.reset(DEPTH_BIAS); _mask.set(DEPTH_BIAS);
return (*
this); }
163 Builder& withWireframe() { _flags.set(WIREFRAME); _mask.set(WIREFRAME);
return (*
this); }
164 Builder& withoutWireframe() { _flags.reset(WIREFRAME); _mask.set(WIREFRAME);
return (*
this); }
166 Builder& withCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) {
167 switch (cullFaceMode) {
168 case graphics::MaterialKey::CullFaceMode::CULL_NONE:
169 _flags.set(CULL_FACE_NONE);
170 _flags.reset(CULL_FACE_FRONT);
172 case graphics::MaterialKey::CullFaceMode::CULL_FRONT:
173 _flags.reset(CULL_FACE_NONE);
174 _flags.set(CULL_FACE_FRONT);
176 case graphics::MaterialKey::CullFaceMode::CULL_BACK:
177 _flags.reset(CULL_FACE_NONE);
178 _flags.reset(CULL_FACE_FRONT);
183 _mask.set(CULL_FACE_NONE);
184 _mask.set(CULL_FACE_FRONT);
188 Builder& withFade() { _flags.set(FADE); _mask.set(FADE);
return (*
this); }
189 Builder& withoutFade() { _flags.reset(FADE); _mask.set(FADE);
return (*
this); }
191 Builder& withMToon() { _flags.set(MTOON); _mask.set(MTOON);
return (*
this); }
192 Builder& withoutMToon() { _flags.reset(MTOON); _mask.set(MTOON);
return (*
this); }
194 Builder& withCustom(uint8_t custom) { _flags &= (~CUSTOM_MASK); _flags |= (custom << CUSTOM_0); _mask |= (CUSTOM_MASK);
return (*
this); }
195 Builder& withoutCustom() { _flags &= (~CUSTOM_MASK); _mask |= (CUSTOM_MASK);
return (*
this); }
202 Filter(
const Filter::Builder& builder) : Filter(builder._flags, builder._mask) {}
203 ShapeKey key()
const {
return ShapeKey(_flags); }
205 friend class ShapePlumber;
210 bool useMaterial()
const {
return _flags[MATERIAL]; }
211 bool hasLightMap()
const {
return _flags[LIGHTMAP]; }
212 bool hasTangents()
const {
return _flags[TANGENTS]; }
213 bool isUnlit()
const {
return _flags[UNLIT]; }
214 bool isTranslucent()
const {
return _flags[TRANSLUCENT]; }
215 bool isDeformed()
const {
return _flags[DEFORMED]; }
216 bool isDualQuatSkinned()
const {
return _flags[DUAL_QUAT_SKINNED]; }
217 bool isDepthBiased()
const {
return _flags[DEPTH_BIAS]; }
218 bool isWireframe()
const {
return _flags[WIREFRAME]; }
219 bool isCullFace()
const {
return !_flags[CULL_FACE_NONE] && !_flags[CULL_FACE_FRONT]; }
220 bool isCullFaceNone()
const {
return _flags[CULL_FACE_NONE] && !_flags[CULL_FACE_FRONT]; }
221 bool isCullFaceFront()
const {
return !_flags[CULL_FACE_NONE] && _flags[CULL_FACE_FRONT]; }
222 bool isFaded()
const {
return _flags[FADE]; }
223 bool isMToon()
const {
return _flags[MTOON]; }
225 bool hasOwnPipeline()
const {
return _flags[OWN_PIPELINE]; }
226 bool isValid()
const {
return !_flags[INVALID]; }
228 uint8_t getCustom()
const {
return (_flags.to_ulong() & CUSTOM_MASK) >> CUSTOM_0; }
229 bool isCustom()
const {
return (_flags.to_ulong() & CUSTOM_MASK); }
234 size_t operator() (
const ShapeKey& key)
const {
235 return std::hash<ShapeKey::Flags>()(key._flags);
242 bool operator()(
const ShapeKey& lhs,
const ShapeKey& rhs)
const {
return lhs._flags == rhs._flags; }
246 inline QDebug operator<<(QDebug debug,
const ShapeKey& key) {
248 if (key.hasOwnPipeline()) {
249 debug <<
"[ShapeKey: OWN_PIPELINE]";
251 debug <<
"[ShapeKey:"
252 <<
"useMaterial:" << key.useMaterial()
253 <<
"hasLightmap:" << key.hasLightMap()
254 <<
"hasTangents:" << key.hasTangents()
255 <<
"isUnlit:" << key.isUnlit()
256 <<
"isTranslucent:" << key.isTranslucent()
257 <<
"isDeformed:" << key.isDeformed()
258 <<
"isDualQuatSkinned:" << key.isDualQuatSkinned()
259 <<
"isDepthBiased:" << key.isDepthBiased()
260 <<
"isWireframe:" << key.isWireframe()
261 <<
"isCullFace:" << key.isCullFace()
262 <<
"isFaded:" << key.isFaded()
263 <<
"isMToon:" << key.isMToon()
267 debug <<
"[ShapeKey: INVALID]";
274 class ShapePipeline {
278 bool albedoTextureUnit{
false };
279 bool normalTextureUnit{
false };
280 bool roughnessTextureUnit{
false };
281 bool metallicTextureUnit{
false };
282 bool emissiveTextureUnit{
false };
283 bool occlusionTextureUnit{
false };
284 bool lightingModelBufferUnit{
false };
285 bool skinClusterBufferUnit{
false };
286 bool materialBufferUnit{
false };
287 bool keyLightBufferUnit{
false };
288 bool lightBufferUnit{
false };
289 bool lightAmbientBufferUnit{
false };
290 bool lightAmbientMapUnit{
false };
291 bool fadeMaskTextureUnit{
false };
292 bool fadeParameterBufferUnit{
false };
293 bool fadeObjectParameterBufferUnit{
false };
294 bool hazeParameterBufferUnit{
false };
295 bool lightClusterGridBufferUnit{
false };
296 bool lightClusterContentBufferUnit{
false };
297 bool lightClusterFrustumBufferUnit{
false };
299 using LocationsPointer = std::shared_ptr<Locations>;
301 using BatchSetter = std::function<void(
const ShapePipeline&, gpu::Batch&, render::Args*)>;
303 using ItemSetter = std::function<void(
const ShapePipeline&, render::Args*,
const render::Item&)>;
305 ShapePipeline(
const gpu::PipelinePointer& pipeline,
const LocationsPointer& locations,
const BatchSetter& batchSetter =
nullptr,
const ItemSetter& itemSetter =
nullptr) :
307 locations(locations),
308 _batchSetter(batchSetter),
309 _itemSetter(itemSetter) {}
313 void prepare(gpu::Batch& batch, Args* args);
315 gpu::PipelinePointer pipeline;
316 std::shared_ptr<Locations> locations;
318 void prepareShapeItem(Args* args,
const ShapeKey& key,
const Item& shape);
321 friend class ShapePlumber;
323 BatchSetter _batchSetter;
324 ItemSetter _itemSetter;
326 using CustomKey = uint8_t;
327 using CustomFactory = std::function<std::shared_ptr<ShapePipeline> (
const ShapePlumber& plumber,
const ShapeKey& key, RenderArgs* args)>;
328 using CustomFactoryMap = std::map<CustomKey, CustomFactory>;
330 static CustomFactoryMap _globalCustomFactoryMap;
332 static CustomKey registerCustomShapePipelineFactory(CustomFactory factory);
335 using ShapePipelinePointer = std::shared_ptr<ShapePipeline>;
339 using Key = ShapeKey;
340 using Filter = Key::Filter;
341 using Pipeline = ShapePipeline;
342 using PipelinePointer = ShapePipelinePointer;
343 using PipelineMap = std::unordered_map<ShapeKey, PipelinePointer, ShapeKey::Hash, ShapeKey::KeyEqual>;
344 using Slot = int32_t;
345 using Locations = Pipeline::Locations;
346 using LocationsPointer = Pipeline::LocationsPointer;
347 using BatchSetter = Pipeline::BatchSetter;
348 using ItemSetter = Pipeline::ItemSetter;
350 void addPipeline(
const Key& key,
const gpu::ShaderPointer& program,
const gpu::StatePointer& state,
351 BatchSetter batchSetter =
nullptr, ItemSetter itemSetter =
nullptr);
352 void addPipeline(
const Filter& filter,
const gpu::ShaderPointer& program,
const gpu::StatePointer& state,
353 BatchSetter batchSetter =
nullptr, ItemSetter itemSetter =
nullptr);
355 const PipelinePointer pickPipeline(RenderArgs* args,
const Key& key)
const;
358 void addPipelineHelper(
const Filter& filter, Key key,
int bit,
const PipelinePointer& pipeline)
const;
359 mutable PipelineMap _pipelineMap;
362 mutable std::unordered_set<Key, Key::Hash, Key::KeyEqual> _missingKeys;
366 using ShapePlumberPointer = std::shared_ptr<ShapePlumber>;