Line data Source code
1 : /* Copyright (C) 2023 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "RenderPassManager.h"
21 :
22 : #include "lib/hash.h"
23 : #include "ps/containers/StaticVector.h"
24 : #include "renderer/backend/vulkan/Device.h"
25 : #include "renderer/backend/vulkan/Mapping.h"
26 : #include "renderer/backend/vulkan/Texture.h"
27 : #include "renderer/backend/vulkan/Utilities.h"
28 :
29 : namespace Renderer
30 : {
31 :
32 : namespace Backend
33 : {
34 :
35 : namespace Vulkan
36 : {
37 :
38 0 : size_t CRenderPassManager::DescHash::operator()(const Desc& desc) const
39 : {
40 0 : size_t seed = 0;
41 0 : hash_combine(seed, desc.sampleCount);
42 :
43 0 : if (desc.colorAttachment.has_value())
44 : {
45 0 : hash_combine(seed, (*desc.colorAttachment).format);
46 0 : hash_combine(seed, (*desc.colorAttachment).loadOp);
47 0 : hash_combine(seed, (*desc.colorAttachment).storeOp);
48 : }
49 : else
50 0 : hash_combine(seed, VK_FORMAT_UNDEFINED);
51 :
52 0 : if (desc.depthStencilAttachment.has_value())
53 : {
54 0 : hash_combine(seed, (*desc.depthStencilAttachment).format);
55 0 : hash_combine(seed, (*desc.depthStencilAttachment).loadOp);
56 0 : hash_combine(seed, (*desc.depthStencilAttachment).storeOp);
57 : }
58 : else
59 0 : hash_combine(seed, VK_FORMAT_UNDEFINED);
60 :
61 0 : return seed;
62 : }
63 :
64 0 : bool CRenderPassManager::DescEqual::operator()(const Desc& lhs, const Desc& rhs) const
65 : {
66 0 : auto compareAttachments = [](const std::optional<Attachment>& lhs, const std::optional<Attachment>& rhs) -> bool
67 : {
68 0 : if (lhs.has_value() != rhs.has_value())
69 0 : return false;
70 0 : if (!lhs.has_value())
71 0 : return true;
72 : return
73 0 : (*lhs).format == (*rhs).format &&
74 0 : (*lhs).loadOp == (*rhs).loadOp &&
75 0 : (*lhs).storeOp == (*rhs).storeOp;
76 : };
77 0 : if (!compareAttachments(lhs.colorAttachment, rhs.colorAttachment))
78 0 : return false;
79 0 : if (!compareAttachments(lhs.depthStencilAttachment, rhs.depthStencilAttachment))
80 0 : return false;
81 0 : return lhs.sampleCount == rhs.sampleCount;
82 : }
83 :
84 0 : CRenderPassManager::CRenderPassManager(CDevice* device)
85 0 : : m_Device(device)
86 : {
87 0 : }
88 :
89 0 : CRenderPassManager::~CRenderPassManager()
90 : {
91 0 : for (const auto& it : m_RenderPassMap)
92 0 : if (it.second != VK_NULL_HANDLE)
93 : {
94 0 : m_Device->ScheduleObjectToDestroy(
95 0 : VK_OBJECT_TYPE_RENDER_PASS, it.second, VK_NULL_HANDLE);
96 : }
97 0 : m_RenderPassMap.clear();
98 0 : }
99 :
100 0 : VkRenderPass CRenderPassManager::GetOrCreateRenderPass(
101 : SColorAttachment* colorAttachment,
102 : SDepthStencilAttachment* depthStencilAttachment)
103 : {
104 0 : Desc desc{};
105 0 : if (colorAttachment)
106 : {
107 0 : CTexture* colorAttachmentTexture = colorAttachment->texture->As<CTexture>();
108 0 : desc.sampleCount = colorAttachmentTexture->GetSampleCount();
109 0 : desc.colorAttachment.emplace(Attachment{
110 0 : colorAttachmentTexture->GetVkFormat(),
111 0 : colorAttachment->loadOp,
112 0 : colorAttachment->storeOp});
113 : }
114 0 : if (depthStencilAttachment)
115 : {
116 0 : CTexture* depthStencilAttachmentTexture = depthStencilAttachment->texture->As<CTexture>();
117 0 : desc.sampleCount = depthStencilAttachmentTexture->GetSampleCount();
118 0 : desc.depthStencilAttachment.emplace(Attachment{
119 0 : depthStencilAttachmentTexture->GetVkFormat(),
120 0 : depthStencilAttachment->loadOp,
121 0 : depthStencilAttachment->storeOp});
122 : }
123 0 : auto it = m_RenderPassMap.find(desc);
124 0 : if (it != m_RenderPassMap.end())
125 0 : return it->second;
126 :
127 0 : uint32_t attachmentCount = 0;
128 0 : PS::StaticVector<VkAttachmentDescription, 4> attachmentDescs;
129 0 : std::optional<VkAttachmentReference> colorAttachmentRef;
130 0 : std::optional<VkAttachmentReference> depthStencilAttachmentRef;
131 :
132 0 : if (colorAttachment)
133 : {
134 0 : CTexture* colorAttachmentTexture = colorAttachment->texture->As<CTexture>();
135 :
136 0 : VkAttachmentDescription colorAttachmentDesc{};
137 0 : colorAttachmentDesc.format = colorAttachmentTexture->GetVkFormat();
138 0 : colorAttachmentDesc.samples = Mapping::FromSampleCount(colorAttachmentTexture->GetSampleCount());
139 0 : colorAttachmentDesc.loadOp = Mapping::FromAttachmentLoadOp(colorAttachment->loadOp);
140 0 : colorAttachmentDesc.storeOp = Mapping::FromAttachmentStoreOp(colorAttachment->storeOp);
141 0 : colorAttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
142 0 : colorAttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
143 :
144 0 : attachmentDescs.emplace_back(std::move(colorAttachmentDesc));
145 :
146 0 : colorAttachmentRef.emplace(VkAttachmentReference{
147 0 : attachmentCount++, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
148 : }
149 :
150 0 : if (depthStencilAttachment)
151 : {
152 0 : CTexture* depthStencilAttachmentTexture = depthStencilAttachment->texture->As<CTexture>();
153 :
154 0 : VkAttachmentDescription depthStencilAttachmentDesc{};
155 0 : depthStencilAttachmentDesc.format = depthStencilAttachmentTexture->GetVkFormat();
156 0 : depthStencilAttachmentDesc.samples = Mapping::FromSampleCount(depthStencilAttachmentTexture->GetSampleCount());
157 0 : depthStencilAttachmentDesc.loadOp = Mapping::FromAttachmentLoadOp(depthStencilAttachment->loadOp);
158 0 : depthStencilAttachmentDesc.storeOp = Mapping::FromAttachmentStoreOp(depthStencilAttachment->storeOp);
159 0 : depthStencilAttachmentDesc.stencilLoadOp = depthStencilAttachmentDesc.loadOp;
160 0 : depthStencilAttachmentDesc.stencilStoreOp = depthStencilAttachmentDesc.storeOp;
161 0 : depthStencilAttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
162 0 : depthStencilAttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
163 :
164 0 : attachmentDescs.emplace_back(std::move(depthStencilAttachmentDesc));
165 :
166 0 : depthStencilAttachmentRef.emplace(VkAttachmentReference{
167 0 : attachmentCount++, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL});
168 : }
169 :
170 0 : VkSubpassDescription subpassDesc{};
171 0 : subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
172 0 : if (colorAttachment)
173 : {
174 0 : subpassDesc.colorAttachmentCount = 1;
175 0 : subpassDesc.pColorAttachments = &(*colorAttachmentRef);
176 : }
177 0 : if (depthStencilAttachment)
178 0 : subpassDesc.pDepthStencilAttachment = &(*depthStencilAttachmentRef);
179 :
180 0 : VkRenderPassCreateInfo renderPassCreateInfo{};
181 0 : renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
182 0 : renderPassCreateInfo.attachmentCount = attachmentDescs.size();
183 0 : renderPassCreateInfo.pAttachments = attachmentDescs.data();
184 0 : renderPassCreateInfo.subpassCount = 1;
185 0 : renderPassCreateInfo.pSubpasses = &subpassDesc;
186 :
187 0 : VkRenderPass renderPass = VK_NULL_HANDLE;
188 0 : ENSURE_VK_SUCCESS(
189 : vkCreateRenderPass(
190 : m_Device->GetVkDevice(), &renderPassCreateInfo, nullptr, &renderPass));
191 0 : it = m_RenderPassMap.emplace(desc, renderPass).first;
192 :
193 0 : return renderPass;
194 : }
195 :
196 : } // namespace Vulkan
197 :
198 : } // namespace Backend
199 :
200 3 : } // namespace Renderer
|