1//
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions
4// are met:
5// * Redistributions of source code must retain the above copyright
6// notice, this list of conditions and the following disclaimer.
7// * Redistributions in binary form must reproduce the above copyright
8// notice, this list of conditions and the following disclaimer in the
9// documentation and/or other materials provided with the distribution.
10// * Neither the name of NVIDIA CORPORATION nor the names of its
11// contributors may be used to endorse or promote products derived
12// from this software without specific prior written permission.
13//
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
15// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
27// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
28// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
29
30#ifndef PX_PHYSICS_SCB_DEFS
31#define PX_PHYSICS_SCB_DEFS
32
33#include "ScbBase.h"
34
35//#define USE_NEW_SYSTEM
36
37#ifdef USE_NEW_SYSTEM
38namespace physx
39{
40namespace Scb
41{
42 template<class ValueType, class CoreType, class SCBType, class AccessType, int id>
43 void setValueT(ValueType value, CoreType& core, SCBType& scb)
44 {
45 if(!scb.isBuffering())
46 {
47 AccessType::setCore(core, value);
48#if PX_SUPPORT_PVD
49 if(scb.getControlState() == ControlState::eIN_SCENE)
50 {
51 Scb::Scene* scene = scb.getScbScene();
52 PX_ASSERT(scene);
53 scene->getScenePvdClient().updatePvdProperties(&scb);
54 }
55#endif
56 }
57 else
58 {
59 AccessType::setBuffered(scb, value);
60 scb.markUpdated(1<<id);
61 }
62 }
63
64 template<class ValueType, class CoreType, class SCBType, class AccessType, int id>
65 ValueType getValueT(const CoreType& core, const SCBType& scb)
66 {
67 if(!scb.isBuffered(1<<id))
68 return AccessType::getCore(core);
69 else
70 return AccessType::getBuffered(scb);
71 }
72
73 template<class CoreType, class SCBType, class AccessType, int id>
74 void syncT(CoreType& core, SCBType& scb)
75 {
76 if(scb.isBuffered(1<<id))
77 AccessType::setCore(core, AccessType::getBuffered(scb));
78 }
79
80 // PT: TODO:
81 // - revisit the sync function, maybe ask for core/buffer params
82 // - revisit the need for explicit BF_XXX flags. I think it's now mainly to skip sync functions in syncState() really.
83 #define SCB_MEMBER(_scb, _getCore, _name, _type, _id) \
84 enum { BF_##_name = 1<<(_id) }; \
85 PX_INLINE void setBuffered##_name(_type v) { reinterpret_cast<Buf*>(getStream())->m##_name = v; } \
86 PX_INLINE _type getBuffered##_name() const { return reinterpret_cast<const Buf*>(getStream())->m##_name; } \
87 struct Fns_##_name \
88 { \
89 static PX_INLINE void setCore(Core& core, _type v) { core.set##_name(v); } \
90 static PX_INLINE void setBuffered(_scb& scb, _type v) { scb.setBuffered##_name(v); } \
91 static PX_INLINE _type getCore(const Core& core) { return core.get##_name(); } \
92 static PX_INLINE _type getBuffered(const _scb& scb) { return scb.getBuffered##_name(); } \
93 }; \
94 PX_INLINE void set##_name(_type v) { setValueT<_type, Core, _scb, Fns_##_name, _id>(v, _getCore, *this); } \
95 PX_INLINE _type get##_name() const { return getValueT<_type, Core, _scb, Fns_##_name, _id>(_getCore, *this); } \
96 PX_INLINE void sync##_name() { syncT<Core, _scb, Fns_##_name, _id>(_getCore, *this); }
97}
98}
99#else
100
101// a Regular attribute of type T is one for which
102// * the SC method takes a single argument of type ArgType<T> (defined below)
103// * Scb either passes that argument through, or dumps it in a buffer to flush later.
104// * PVD is notified when the variable changes
105//
106// For each such, we can define static methods to read and write the core and buffered variables,
107// and capture the buffering logic in the BufferedAccess class.
108//
109// The dummy arg is necessary here because ISO permits partial specialization of member templates
110// but not full specialization.
111//
112// putting just accessors and mutators here allows us to change the behavior just by varying the
113// BufferAccess template (e.g. to compile without buffering), and also to size-reduce that template
114// by passing function pointers if necessary
115
116#define SCB_REGULAR_ATTRIBUTE(_val, _type, _name) \
117enum { BF_##_name = 1<<(_val) }; \
118_type m##_name; \
119template<PxU32 Dummy> struct Fns<1<<(_val),Dummy> \
120{ \
121 typedef typename ArgType<_type>::Type Arg; \
122 enum { flag = 1<<(_val) }; \
123 static PX_FORCE_INLINE Arg getBuffered(const Buf& buf) { return Arg(buf.m##_name);} \
124 static PX_FORCE_INLINE void setBuffered(Buf& buf, Arg v) { buf.m##_name = v;} \
125 static PX_FORCE_INLINE Arg getCore(const Core& core) { return Arg(core.get##_name());} \
126 static PX_FORCE_INLINE void setCore(Core& core, Arg v) { core.set##_name(v);} \
127};
128
129#define SCB_REGULAR_ATTRIBUTE_ALIGNED(_val, _type, _name, _alignment) \
130enum { BF_##_name = 1<<(_val) }; \
131PX_ALIGN(_alignment, _type) m##_name; \
132template<PxU32 Dummy> struct Fns<1<<(_val),Dummy> \
133{ \
134 typedef typename ArgType<_type>::Type Arg; \
135 enum { flag = 1<<(_val) }; \
136 static PX_FORCE_INLINE Arg getBuffered(const Buf& buf) { return buf.m##_name;} \
137 static PX_FORCE_INLINE void setBuffered(Buf& buf, Arg v) { buf.m##_name = v;} \
138 static PX_FORCE_INLINE Arg getCore(const Core& core) { return core.get##_name();} \
139 static PX_FORCE_INLINE void setCore(Core& core, Arg v) { core.set##_name(v);} \
140};
141
142namespace physx
143{
144namespace Scb
145{
146class Scene;
147
148template<typename T> struct ArgType { typedef T Type; };
149template<> struct ArgType<PxVec3> { typedef const PxVec3& Type; };
150template<> struct ArgType<PxTransform> { typedef const PxTransform& Type; };
151template<> struct ArgType<PxQuat> { typedef const PxQuat& Type; };
152template<> struct ArgType<PxPlane> { typedef const PxPlane& Type; };
153template<> struct ArgType<PxFilterData> { typedef const PxFilterData& Type; };
154
155// TODO: should be able to size-reduce this if necessary by just generating one set per
156// arg type instead of one per arg, by passing function pointers to the accessors/mutators/flag
157// instead of instancing per type.
158
159template<class Buf, class Core, class ScbClass, class BaseClass=Scb::Base> // BaseClass: introduced to have Scb::Body use custom location for storing buffered property flags
160struct BufferedAccess
161{
162 template<typename Fns>
163 static PX_FORCE_INLINE typename Fns::Arg read(const BaseClass& base, const Core& core)
164 {
165 /*return base.isBuffered(Fns::flag) ? Fns::getBuffered(*reinterpret_cast<const Buf*>(base.getStream()))
166 : Fns::getCore(core);*/
167
168 if (base.isBuffered(Fns::flag))
169 {
170 return Fns::getBuffered(*reinterpret_cast<const Buf*>(base.getStream()));
171 }
172 return Fns::getCore(core);
173
174 }
175
176 template<typename Fns>
177 static PX_FORCE_INLINE void write(BaseClass& base, Core& core, typename Fns::Arg v)
178 {
179 if(!base.isBuffering())
180 {
181 Fns::setCore(core, v);
182#if PX_SUPPORT_PVD
183 if(base.getControlState() == ControlState::eIN_SCENE)
184 {
185 Scb::Scene* scene = base.getScbScene();
186 PX_ASSERT(scene);
187 scene->getScenePvdClient().updatePvdProperties(static_cast<ScbClass*>(&base));
188 }
189#endif
190 }
191 else
192 {
193 Fns::setBuffered(*reinterpret_cast<Buf*>(base.getStream()), v);
194 base.markUpdated(Fns::flag);
195 }
196 }
197
198 template<typename Fns>
199 static PX_FORCE_INLINE void flush(const BaseClass& base, Core& core, const Buf& buf)
200 {
201 if(base.isBuffered(Fns::flag))
202 Fns::setCore(core, Fns::getBuffered(buf));
203 }
204};
205
206}
207}
208#endif
209
210#endif
211

source code of qtquick3dphysics/src/3rdparty/PhysX/source/physx/src/buffering/ScbDefs.h