Diligent Engine  v.2.4.g
DeviceObjectBase.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 #pragma once
29 
32 
33 #include <cstring>
34 #include <cstdio>
35 #include "RefCntAutoPtr.hpp"
36 #include "ObjectBase.hpp"
37 #include "UniqueIdentifier.hpp"
38 #include "EngineMemory.h"
39 
40 namespace Diligent
41 {
42 
44 template <class BaseInterface, typename RenderDeviceImplType, typename ObjectDescType>
45 class DeviceObjectBase : public ObjectBase<BaseInterface>
46 {
47 public:
49 
56  RenderDeviceImplType* pDevice,
57  const ObjectDescType& ObjDesc,
58  bool bIsDeviceInternal = false) :
59  // clang-format off
60  TBase {pRefCounters},
61  m_pDevice {pDevice },
62  m_Desc {ObjDesc },
63  m_bIsDeviceInternal{bIsDeviceInternal}
64  //clang-format on
65  {
66  // Do not keep strong reference to the device if the object is an internal device object
68  {
69  m_pDevice->AddRef();
70  }
71 
72  if (ObjDesc.Name != nullptr)
73  {
74  auto size = strlen(ObjDesc.Name) + 1;
75  auto* NameCopy = ALLOCATE(GetStringAllocator(), "Object name copy", char, size);
76  memcpy(NameCopy, ObjDesc.Name, size);
77  m_Desc.Name = NameCopy;
78  }
79  else
80  {
81  size_t size = 16 + 2 + 1; // 0x12345678
82  auto* AddressStr = ALLOCATE(GetStringAllocator(), "Object address string", char, size);
83  snprintf(AddressStr, size, "0x%llX", static_cast<unsigned long long>(reinterpret_cast<size_t>(this)));
84  m_Desc.Name = AddressStr;
85  }
86 
87  // !!!WARNING!!!
88  // We cannot add resource to the hash table from here, because the object
89  // has not been completely created yet and the reference counters object
90  // is not initialized!
91  //m_pDevice->AddResourceToHash( this ); - ERROR!
92  }
93 
94  // clang-format off
95  DeviceObjectBase (const DeviceObjectBase& ) = delete;
96  DeviceObjectBase ( DeviceObjectBase&&) = delete;
99  // clang-format on
100 
102  {
103  FREE(GetStringAllocator(), const_cast<Char*>(m_Desc.Name));
104 
105  if (!m_bIsDeviceInternal)
106  {
107  m_pDevice->Release();
108  }
109  }
110 
111  inline virtual Atomics::Long DILIGENT_CALL_TYPE Release() override final
112  {
113  // Render device owns allocators for all types of device objects,
114  // so it must be destroyed after all device objects are released.
115  // Consider the following scenario: an object A owns the last strong
116  // reference to the device:
117  //
118  // 1. A::~A() completes
119  // 2. A::~DeviceObjectBase() completes
120  // 3. A::m_pDevice is released
121  // Render device is destroyed, all allocators are invalid
122  // 4. RefCountersImpl::ObjectWrapperBase::DestroyObject() calls
123  // m_pAllocator->Free(m_pObject) - crash!
124 
126  return TBase::Release(
127  [&]() //
128  {
129  // We must keep the device alive while the object is being destroyed
130  // Note that internal device objects do not keep strong reference to the device
131  if (!m_bIsDeviceInternal)
132  {
133  pDevice = m_pDevice;
134  }
135  });
136  }
137 
138  IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_DeviceObject, TBase)
139 
140  virtual const ObjectDescType& DILIGENT_CALL_TYPE GetDesc() const override final
141  {
142  return m_Desc;
143  }
144 
146  virtual Int32 DILIGENT_CALL_TYPE GetUniqueID() const override final
147  {
153  return m_UniqueID.GetID();
154  }
155 
157  virtual void DILIGENT_CALL_TYPE SetUserData(IObject* pUserData) override final
158  {
159  m_pUserData = pUserData;
160  }
161 
163  virtual IObject* DILIGENT_CALL_TYPE GetUserData() const override final
164  {
165  return m_pUserData.RawPtr<IObject>();
166  }
167 
168  static bool IsSameObject(const DeviceObjectBase* pObj1, const DeviceObjectBase* pObj2)
169  {
170  UniqueIdentifier Id1 = (pObj1 != nullptr) ? pObj1->GetUniqueID() : 0;
171  UniqueIdentifier Id2 = (pObj2 != nullptr) ? pObj2->GetUniqueID() : 0;
172  return Id1 == Id2;
173  }
174 
175  RenderDeviceImplType* GetDevice() const { return m_pDevice; }
176 
177 protected:
179  RenderDeviceImplType* const m_pDevice;
180 
182  ObjectDescType m_Desc;
183 
184  // Template argument is only used to separate counters for
185  // different groups of objects
188 
190 };
191 
192 } // namespace Diligent
Diligent::DeviceObjectBase::Release
virtual Atomics::Long Release() override final
Definition: DeviceObjectBase.hpp:111
Diligent::DeviceObjectBase::m_pUserData
RefCntAutoPtr< IObject > m_pUserData
Definition: DeviceObjectBase.hpp:189
ObjectBase.hpp
Diligent::DeviceObjectBase::operator=
DeviceObjectBase & operator=(const DeviceObjectBase &)=delete
Diligent::IReferenceCounters
Base interface for a reference counter object that stores the number of strong and weak references an...
Definition: ReferenceCounters.h:44
BasicAtomics::Long
long Long
Definition: BasicAtomics.hpp:34
Diligent::Char
char Char
Definition: BasicTypes.h:64
Diligent::DeviceObjectBase::m_pDevice
RenderDeviceImplType *const m_pDevice
Pointer to the device.
Definition: DeviceObjectBase.hpp:179
Diligent::UniqueIdHelper< BaseInterface >
Diligent::DeviceObjectBase::m_bIsDeviceInternal
const bool m_bIsDeviceInternal
Definition: DeviceObjectBase.hpp:187
Diligent::IObject
Base interface for all dynamic objects in the engine.
Definition: Object.h:41
Diligent::DeviceObjectBase::GetDesc
virtual const ObjectDescType & GetDesc() const override final
Definition: DeviceObjectBase.hpp:140
Diligent::DeviceObjectBase::m_Desc
ObjectDescType m_Desc
Object description.
Definition: DeviceObjectBase.hpp:182
Diligent::DeviceObjectBase::SetUserData
virtual void SetUserData(IObject *pUserData) override final
Implementation of IDeviceObject::SetUserData.
Definition: DeviceObjectBase.hpp:157
Diligent::DeviceObjectBase::~DeviceObjectBase
virtual ~DeviceObjectBase()
Definition: DeviceObjectBase.hpp:101
Diligent::DeviceObjectBase::m_UniqueID
UniqueIdHelper< BaseInterface > m_UniqueID
Definition: DeviceObjectBase.hpp:186
Diligent::ObjectBase
Template class implementing base functionality for an object.
Definition: ObjectBase.hpp:66
FREE
#define FREE(Allocator, Ptr)
Definition: EngineMemory.h:48
Diligent::Int32
int32_t Int32
32-bit signed integer
Definition: BasicTypes.h:46
EngineMemory.h
UniqueIdentifier.hpp
IMPLEMENT_QUERY_INTERFACE_IN_PLACE
#define IMPLEMENT_QUERY_INTERFACE_IN_PLACE(InterfaceID, ParentClassName)
Definition: ObjectBase.hpp:59
Diligent::DeviceObjectBase::GetUserData
virtual IObject * GetUserData() const override final
Implementation of IDeviceObject::GetUserData.
Definition: DeviceObjectBase.hpp:163
Diligent::RefCntAutoPtr
Template class that implements reference counting.
Definition: RefCntAutoPtr.hpp:73
DILIGENT_CALL_TYPE
#define DILIGENT_CALL_TYPE
Definition: CommonDefinitions.h:45
Diligent::UniqueIdHelper::GetID
UniqueIdentifier GetID() const noexcept
Definition: UniqueIdentifier.hpp:64
Diligent::RefCountedObject< BaseInterface >::Release
virtual ReferenceCounterValueType Release() override
Definition: RefCountedObjectImpl.hpp:552
Diligent::DeviceObjectBase::GetDevice
RenderDeviceImplType * GetDevice() const
Definition: DeviceObjectBase.hpp:175
RefCntAutoPtr.hpp
Diligent::DeviceObjectBase::GetUniqueID
virtual Int32 GetUniqueID() const override final
Returns unique identifier.
Definition: DeviceObjectBase.hpp:146
Diligent::GetStringAllocator
IMemoryAllocator & GetStringAllocator()
Definition: EngineMemory.cpp:56
Diligent::DeviceObjectBase::IsSameObject
static bool IsSameObject(const DeviceObjectBase *pObj1, const DeviceObjectBase *pObj2)
Definition: DeviceObjectBase.hpp:168
ALLOCATE
#define ALLOCATE(Allocator, Desc, Type, Count)
Definition: EngineMemory.h:47
Diligent::UniqueIdentifier
Int32 UniqueIdentifier
Definition: UniqueIdentifier.hpp:36
Diligent::DeviceObjectBase::TBase
ObjectBase< BaseInterface > TBase
Definition: DeviceObjectBase.hpp:48
Diligent::DeviceObjectBase::DeviceObjectBase
DeviceObjectBase(IReferenceCounters *pRefCounters, RenderDeviceImplType *pDevice, const ObjectDescType &ObjDesc, bool bIsDeviceInternal=false)
Definition: DeviceObjectBase.hpp:55
Diligent::DeviceObjectBase
Template class implementing base functionality of the device object.
Definition: DeviceObjectBase.hpp:45
Diligent
The library uses Direct3D-style math:
Definition: AdvancedMath.hpp:37