Diligent Engine  v.2.4.g
RenderPassBase.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 <vector>
34 #include <utility>
35 
36 #include "RenderPass.h"
37 #include "DeviceObjectBase.hpp"
38 #include "RenderDeviceBase.hpp"
39 
40 namespace Diligent
41 {
42 
43 void ValidateRenderPassDesc(const RenderPassDesc& Desc) noexcept(false);
44 
45 template <typename RenderDeviceImplType>
47 
48 template <>
50 {
51  if (State == RESOURCE_STATE_RESOLVE_DEST)
52  {
53  // In Vulkan resolve attachments must be in VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL state.
54  // It is important to correct the state because outside of render pass RESOURCE_STATE_RESOLVE_DEST maps
55  // to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
57  }
58 }
59 
61 
63 template <typename EngineImplTraits>
64 class RenderPassBase : public DeviceObjectBase<typename EngineImplTraits::RenderPassInterface, typename EngineImplTraits::RenderDeviceImplType, RenderPassDesc>
65 {
66 public:
67  // Base interface this class inherits (e.g. IRenderPassVk)
68  using BaseInterface = typename EngineImplTraits::RenderPassInterface;
69 
70  // Render device implementation type (RenderDeviceD3D12Impl, RenderDeviceVkImpl, etc.).
71  using RenderDeviceImplType = typename EngineImplTraits::RenderDeviceImplType;
72 
74 
81  RenderDeviceImplType* pDevice,
82  const RenderPassDesc& Desc,
83  bool bIsDeviceInternal = false) :
84  TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}
85  {
87 
88  if (Desc.AttachmentCount != 0)
89  {
90  auto* pAttachments =
91  ALLOCATE(GetRawAllocator(), "Memory for RenderPassAttachmentDesc array", RenderPassAttachmentDesc, Desc.AttachmentCount);
92  this->m_Desc.pAttachments = pAttachments;
93  for (Uint32 i = 0; i < Desc.AttachmentCount; ++i)
94  {
95  pAttachments[i] = Desc.pAttachments[i];
96  _CorrectAttachmentState<RenderDeviceImplType>(pAttachments[i].FinalState);
97  }
98  }
99 
100  Uint32 TotalAttachmentReferencesCount = 0;
101  Uint32 TotalPreserveAttachmentsCount = 0;
102  CountSubpassAttachmentReferences(Desc, TotalAttachmentReferencesCount, TotalPreserveAttachmentsCount);
103  if (TotalAttachmentReferencesCount != 0)
104  {
105  m_pAttachmentReferences = ALLOCATE(GetRawAllocator(), "Memory for subpass attachment references array", AttachmentReference, TotalAttachmentReferencesCount);
106  }
107  if (TotalPreserveAttachmentsCount != 0)
108  {
109  m_pPreserveAttachments = ALLOCATE(GetRawAllocator(), "Memory for subpass preserve attachments array", Uint32, TotalPreserveAttachmentsCount);
110  }
111 
112  m_AttachmentStates.resize(Desc.AttachmentCount * Desc.SubpassCount);
113  m_AttachmentFirstLastUse.resize(Desc.AttachmentCount, std::pair<Uint32, Uint32>{ATTACHMENT_UNUSED, 0});
114 
115  auto* pCurrAttachmentRef = m_pAttachmentReferences;
116  auto* pCurrPreserveAttachment = m_pPreserveAttachments;
117  VERIFY(Desc.SubpassCount != 0, "Render pass must have at least one subpass");
118  auto* pSubpasses =
119  ALLOCATE(GetRawAllocator(), "Memory for SubpassDesc array", SubpassDesc, Desc.SubpassCount);
120  this->m_Desc.pSubpasses = pSubpasses;
121  for (Uint32 subpass = 0; subpass < Desc.SubpassCount; ++subpass)
122  {
123  for (Uint32 att = 0; att < Desc.AttachmentCount; ++att)
124  {
125  SetAttachmentState(subpass, att, subpass > 0 ? GetAttachmentState(subpass - 1, att) : Desc.pAttachments[subpass].InitialState);
126  }
127 
128  const auto& SrcSubpass = Desc.pSubpasses[subpass];
129  auto& DstSubpass = pSubpasses[subpass];
130 
131  auto UpdateAttachmentStateAndFirstUseSubpass = [this, subpass](const AttachmentReference& AttRef) //
132  {
133  if (AttRef.AttachmentIndex != ATTACHMENT_UNUSED)
134  {
135  SetAttachmentState(subpass, AttRef.AttachmentIndex, AttRef.State);
136  auto& FirstLastUse = m_AttachmentFirstLastUse[AttRef.AttachmentIndex];
137  if (FirstLastUse.first == ATTACHMENT_UNUSED)
138  FirstLastUse.first = subpass;
139  FirstLastUse.second = subpass;
140  }
141  };
142 
143  DstSubpass = SrcSubpass;
144  if (SrcSubpass.InputAttachmentCount != 0)
145  {
146  DstSubpass.pInputAttachments = pCurrAttachmentRef;
147  for (Uint32 input_attachment = 0; input_attachment < SrcSubpass.InputAttachmentCount; ++input_attachment, ++pCurrAttachmentRef)
148  {
149  *pCurrAttachmentRef = SrcSubpass.pInputAttachments[input_attachment];
150  UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef);
151  }
152  }
153  else
154  DstSubpass.pInputAttachments = nullptr;
155 
156  if (SrcSubpass.RenderTargetAttachmentCount != 0)
157  {
158  DstSubpass.pRenderTargetAttachments = pCurrAttachmentRef;
159  for (Uint32 rt_attachment = 0; rt_attachment < SrcSubpass.RenderTargetAttachmentCount; ++rt_attachment, ++pCurrAttachmentRef)
160  {
161  *pCurrAttachmentRef = SrcSubpass.pRenderTargetAttachments[rt_attachment];
162  UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef);
163  }
164 
165  if (DstSubpass.pResolveAttachments)
166  {
167  DstSubpass.pResolveAttachments = pCurrAttachmentRef;
168  for (Uint32 rslv_attachment = 0; rslv_attachment < SrcSubpass.RenderTargetAttachmentCount; ++rslv_attachment, ++pCurrAttachmentRef)
169  {
170  *pCurrAttachmentRef = SrcSubpass.pResolveAttachments[rslv_attachment];
171  _CorrectAttachmentState<RenderDeviceImplType>(pCurrAttachmentRef->State);
172  UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef);
173  }
174  }
175  }
176  else
177  {
178  DstSubpass.pRenderTargetAttachments = nullptr;
179  DstSubpass.pResolveAttachments = nullptr;
180  }
181 
182  if (SrcSubpass.pDepthStencilAttachment != nullptr)
183  {
184  DstSubpass.pDepthStencilAttachment = pCurrAttachmentRef;
185  *(pCurrAttachmentRef++) = *SrcSubpass.pDepthStencilAttachment;
186  UpdateAttachmentStateAndFirstUseSubpass(*SrcSubpass.pDepthStencilAttachment);
187  }
188 
189  if (SrcSubpass.PreserveAttachmentCount != 0)
190  {
191  DstSubpass.pPreserveAttachments = pCurrPreserveAttachment;
192  for (Uint32 prsv_attachment = 0; prsv_attachment < SrcSubpass.PreserveAttachmentCount; ++prsv_attachment)
193  *(pCurrPreserveAttachment++) = SrcSubpass.pPreserveAttachments[prsv_attachment];
194  }
195  else
196  DstSubpass.pPreserveAttachments = nullptr;
197  }
198  VERIFY_EXPR(pCurrAttachmentRef - m_pAttachmentReferences == static_cast<ptrdiff_t>(TotalAttachmentReferencesCount));
199  VERIFY_EXPR(pCurrPreserveAttachment - m_pPreserveAttachments == static_cast<ptrdiff_t>(TotalPreserveAttachmentsCount));
200 
201  if (Desc.DependencyCount != 0)
202  {
203  auto* pDependencies =
204  ALLOCATE(GetRawAllocator(), "Memory for SubpassDependencyDesc array", SubpassDependencyDesc, Desc.DependencyCount);
205  this->m_Desc.pDependencies = pDependencies;
206  for (Uint32 i = 0; i < Desc.DependencyCount; ++i)
207  {
208  pDependencies[i] = Desc.pDependencies[i];
209  }
210  }
211  }
212 
214  {
215  auto& RawAllocator = GetRawAllocator();
216  if (this->m_Desc.pAttachments != nullptr)
217  RawAllocator.Free(const_cast<RenderPassAttachmentDesc*>(this->m_Desc.pAttachments));
218  if (this->m_Desc.pSubpasses != nullptr)
219  RawAllocator.Free(const_cast<SubpassDesc*>(this->m_Desc.pSubpasses));
220  if (this->m_Desc.pDependencies != nullptr)
221  RawAllocator.Free(const_cast<SubpassDependencyDesc*>(this->m_Desc.pDependencies));
222  if (m_pAttachmentReferences != nullptr)
223  RawAllocator.Free(m_pAttachmentReferences);
224  if (m_pPreserveAttachments != nullptr)
225  RawAllocator.Free(m_pPreserveAttachments);
226  }
227 
229 
230  RESOURCE_STATE GetAttachmentState(Uint32 Subpass, Uint32 Attachment) const
231  {
232  VERIFY_EXPR(Attachment < this->m_Desc.AttachmentCount);
233  VERIFY_EXPR(Subpass < this->m_Desc.SubpassCount);
234  return m_AttachmentStates[this->m_Desc.AttachmentCount * Subpass + Attachment];
235  }
236 
237  std::pair<Uint32, Uint32> GetAttachmentFirstLastUse(Uint32 Attachment) const
238  {
239  return m_AttachmentFirstLastUse[Attachment];
240  }
241 
242 protected:
244  Uint32& TotalAttachmentReferencesCount,
245  Uint32& TotalPreserveAttachmentsCount)
246  {
247  TotalAttachmentReferencesCount = 0;
248  TotalPreserveAttachmentsCount = 0;
249  for (Uint32 i = 0; i < Desc.SubpassCount; ++i)
250  {
251  const auto& Subpass = Desc.pSubpasses[i];
252  TotalAttachmentReferencesCount += Subpass.InputAttachmentCount;
253  TotalAttachmentReferencesCount += Subpass.RenderTargetAttachmentCount;
254  if (Subpass.pResolveAttachments != nullptr)
255  TotalAttachmentReferencesCount += Subpass.RenderTargetAttachmentCount;
256  if (Subpass.pDepthStencilAttachment != nullptr)
257  TotalAttachmentReferencesCount += 1;
258  TotalPreserveAttachmentsCount += Subpass.PreserveAttachmentCount;
259  }
260  }
261 
262 private:
263  void SetAttachmentState(Uint32 Subpass, Uint32 Attachment, RESOURCE_STATE State)
264  {
265  VERIFY_EXPR(Attachment < this->m_Desc.AttachmentCount);
266  VERIFY_EXPR(Subpass < this->m_Desc.SubpassCount);
267  m_AttachmentStates[this->m_Desc.AttachmentCount * Subpass + Attachment] = State;
268  }
269 
270  AttachmentReference* m_pAttachmentReferences = nullptr;
271  Uint32* m_pPreserveAttachments = nullptr;
272 
273  // Attachment states during each subpass
274  std::vector<RESOURCE_STATE> m_AttachmentStates;
275 
276  // The index of the subpass where the attachment is first used
277  std::vector<std::pair<Uint32, Uint32>> m_AttachmentFirstLastUse;
278 };
279 
280 } // namespace Diligent
Diligent::RenderPassBase::GetAttachmentFirstLastUse
std::pair< Uint32, Uint32 > GetAttachmentFirstLastUse(Uint32 Attachment) const
Definition: RenderPassBase.hpp:237
Diligent::IReferenceCounters
Base interface for a reference counter object that stores the number of strong and weak references an...
Definition: ReferenceCounters.h:44
Diligent::SubpassDesc
struct SubpassDesc SubpassDesc
Definition: RenderPass.h:289
DeviceObjectBase.hpp
Diligent::_CorrectAttachmentState< class RenderDeviceVkImpl >
void _CorrectAttachmentState< class RenderDeviceVkImpl >(RESOURCE_STATE &State)
Definition: RenderPassBase.hpp:49
Diligent::ValidateRenderPassDesc
void ValidateRenderPassDesc(const RenderPassDesc &Desc) noexcept(false)
Definition: RenderPassBase.cpp:36
Diligent::DeviceObjectBase< EngineImplTraits::RenderPassInterface, EngineImplTraits::RenderDeviceImplType, RenderPassDesc >::m_Desc
RenderPassDesc m_Desc
Object description.
Definition: DeviceObjectBase.hpp:182
Diligent::RenderPassBase::RenderPassBase
RenderPassBase(IReferenceCounters *pRefCounters, RenderDeviceImplType *pDevice, const RenderPassDesc &Desc, bool bIsDeviceInternal=false)
Definition: RenderPassBase.hpp:80
Diligent::RenderPassDesc::SubpassCount
Uint32 SubpassCount
The number of subpasses in the render pass.
Definition: RenderPass.h:350
Diligent::RenderPassBase::TDeviceObjectBase
DeviceObjectBase< BaseInterface, RenderDeviceImplType, RenderPassDesc > TDeviceObjectBase
Definition: RenderPassBase.hpp:73
Diligent::RenderPassDesc
Render pass description.
Definition: RenderPass.h:341
Diligent::SubpassDependencyDesc
Subpass dependency description.
Definition: RenderPass.h:295
Diligent::RenderPassBase< EngineGLImplTraits >::RenderDeviceImplType
typename EngineGLImplTraits ::RenderDeviceImplType RenderDeviceImplType
Definition: RenderPassBase.hpp:71
Diligent::AttachmentReference
struct AttachmentReference AttachmentReference
Definition: RenderPass.h:182
RenderDeviceBase.hpp
Diligent::RenderPassBase::GetAttachmentState
RESOURCE_STATE GetAttachmentState(Uint32 Subpass, Uint32 Attachment) const
Definition: RenderPassBase.hpp:230
Diligent::RenderPassDesc
struct RenderPassDesc RenderPassDesc
Definition: RenderPass.h:361
Diligent::GetRawAllocator
IMemoryAllocator & GetRawAllocator()
Returns raw memory allocator.
Definition: EngineMemory.cpp:51
Diligent::RenderPassBase::CountSubpassAttachmentReferences
static void CountSubpassAttachmentReferences(const RenderPassDesc &Desc, Uint32 &TotalAttachmentReferencesCount, Uint32 &TotalPreserveAttachmentsCount)
Definition: RenderPassBase.hpp:243
IMPLEMENT_QUERY_INTERFACE_IN_PLACE
#define IMPLEMENT_QUERY_INTERFACE_IN_PLACE(InterfaceID, ParentClassName)
Definition: ObjectBase.hpp:59
Diligent::SubpassDesc
Render pass subpass decription.
Definition: RenderPass.h:186
Diligent::SubpassDependencyDesc
struct SubpassDependencyDesc SubpassDependencyDesc
Definition: RenderPass.h:338
Diligent::RESOURCE_STATE_RENDER_TARGET
@ RESOURCE_STATE_RENDER_TARGET
The resource is accessed as a render target.
Definition: GraphicsTypes.h:2832
Diligent::RenderPassDesc::pAttachments
const RenderPassAttachmentDesc * pAttachments
Pointer to the array of subpass attachments, see Diligent::RenderPassAttachmentDesc.
Definition: RenderPass.h:347
Diligent::RESOURCE_STATE_RESOLVE_DEST
@ RESOURCE_STATE_RESOLVE_DEST
The resource is used as the destination in a resolve operation.
Definition: GraphicsTypes.h:2859
Diligent::Uint32
uint32_t Uint32
32-bit unsigned integer
Definition: BasicTypes.h:51
RenderPass.h
Diligent::SubpassDesc::InputAttachmentCount
Uint32 InputAttachmentCount
The number of input attachments the subpass uses.
Definition: RenderPass.h:189
Diligent::RenderPassBase::~RenderPassBase
~RenderPassBase()
Definition: RenderPassBase.hpp:213
Diligent::RenderPassBase
Template class implementing base functionality of the render pass object.
Definition: RenderPassBase.hpp:64
Diligent::RenderPassDesc::pSubpasses
const SubpassDesc * pSubpasses
Pointer to the array of subpass descriptions, see Diligent::SubpassDesc.
Definition: RenderPass.h:353
Diligent::RenderPassAttachmentDesc
Render pass attachment description.
Definition: RenderPass.h:88
Diligent::RenderPassDesc::pDependencies
const SubpassDependencyDesc * pDependencies
Pointer to the array of subpass dependencies, see Diligent::SubpassDependencyDesc.
Definition: RenderPass.h:359
VERIFY_EXPR
#define VERIFY_EXPR(...)
Definition: DebugUtilities.hpp:79
VERIFY
#define VERIFY(...)
Definition: DebugUtilities.hpp:76
Diligent::_CorrectAttachmentState
void _CorrectAttachmentState(RESOURCE_STATE &State)
Definition: RenderPassBase.hpp:46
Diligent::RESOURCE_STATE
RESOURCE_STATE
Resource usage state.
Definition: GraphicsTypes.h:2814
Diligent::RenderPassBase< EngineGLImplTraits >::BaseInterface
typename EngineGLImplTraits ::RenderPassInterface BaseInterface
Definition: RenderPassBase.hpp:68
ALLOCATE
#define ALLOCATE(Allocator, Desc, Type, Count)
Definition: EngineMemory.h:47
Diligent::RenderPassDesc::AttachmentCount
Uint32 AttachmentCount
The number of attachments used by the render pass.
Definition: RenderPass.h:344
ATTACHMENT_UNUSED
#define ATTACHMENT_UNUSED
Definition: RenderPass.h:143
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