| Flutter Impeller |

render_pass_builder_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h"
6
7 #include "impeller/core/formats.h"
8 #include "impeller/renderer/backend/vulkan/formats_vk.h"
9
10 namespace impeller {
11
12 constexpr auto kSelfDependencySrcStageMask =
13 vk::PipelineStageFlagBits::eColorAttachmentOutput;
14 constexpr auto kSelfDependencySrcAccessMask =
15 vk::AccessFlagBits::eColorAttachmentWrite;
16
17 constexpr auto kSelfDependencyDstStageMask =
18 vk::PipelineStageFlagBits::eFragmentShader;
19 constexpr auto kSelfDependencyDstAccessMask =
20 vk::AccessFlagBits::eInputAttachmentRead;
21
22 constexpr auto kSelfDependencyFlags = vk::DependencyFlagBits::eByRegion;
23
24 RenderPassBuilderVK::RenderPassBuilderVK() = default;
25
26 RenderPassBuilderVK::~RenderPassBuilderVK() = default;
27
28 RenderPassBuilderVK& RenderPassBuilderVK::SetColorAttachment(
29 size_t index,
30 PixelFormat format,
31 SampleCount sample_count,
32 LoadAction load_action,
33 StoreAction store_action,
34 vk::ImageLayout current_layout) {
35 vk::AttachmentDescription desc;
36 desc.format = ToVKImageFormat(format);
37 desc.samples = ToVKSampleCount(sample_count);
38 desc.loadOp = ToVKAttachmentLoadOp(load_action);
39 desc.storeOp = ToVKAttachmentStoreOp(store_action, false);
40 desc.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
41 desc.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
42 if (load_action == LoadAction::kLoad) {
43 desc.initialLayout = current_layout;
44 } else {
45 desc.initialLayout = vk::ImageLayout::eUndefined;
46 }
47 desc.finalLayout = vk::ImageLayout::eGeneral;
48
49 const bool performs_resolves = StoreActionPerformsResolve(store_action);
50 if (index == 0u) {
51 color0_ = desc;
52
53 if (performs_resolves) {
54 desc.storeOp = ToVKAttachmentStoreOp(store_action, true);
55 desc.samples = vk::SampleCountFlagBits::e1;
56 color0_resolve_ = desc;
57 } else {
58 color0_resolve_ = std::nullopt;
59 }
60 } else {
61 colors_[index] = desc;
62 if (performs_resolves) {
63 desc.storeOp = ToVKAttachmentStoreOp(store_action, true);
64 desc.samples = vk::SampleCountFlagBits::e1;
65 resolves_[index] = desc;
66 } else {
67 resolves_.erase(index);
68 }
69 }
70 return *this;
71 }
72
73 RenderPassBuilderVK& RenderPassBuilderVK::SetDepthStencilAttachment(
74 PixelFormat format,
75 SampleCount sample_count,
76 LoadAction load_action,
77 StoreAction store_action) {
78 vk::AttachmentDescription desc;
79 desc.format = ToVKImageFormat(format);
80 desc.samples = ToVKSampleCount(sample_count);
81 desc.loadOp = ToVKAttachmentLoadOp(load_action);
82 desc.storeOp = ToVKAttachmentStoreOp(store_action, false);
83 desc.stencilLoadOp = desc.loadOp; // Not separable in Impeller.
84 desc.stencilStoreOp = desc.storeOp; // Not separable in Impeller.
85 desc.initialLayout = vk::ImageLayout::eUndefined;
86 desc.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
87 depth_stencil_ = desc;
88 return *this;
89 }
90
91 RenderPassBuilderVK& RenderPassBuilderVK::SetStencilAttachment(
92 PixelFormat format,
93 SampleCount sample_count,
94 LoadAction load_action,
95 StoreAction store_action) {
96 vk::AttachmentDescription desc;
97 desc.format = ToVKImageFormat(format);
98 desc.samples = ToVKSampleCount(sample_count);
99 desc.loadOp = vk::AttachmentLoadOp::eDontCare;
100 desc.storeOp = vk::AttachmentStoreOp::eDontCare;
101 desc.stencilLoadOp = ToVKAttachmentLoadOp(load_action);
102 desc.stencilStoreOp = ToVKAttachmentStoreOp(store_action, false);
103 desc.initialLayout = vk::ImageLayout::eUndefined;
104 desc.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
105 depth_stencil_ = desc;
106 return *this;
107 }
108
109 vk::UniqueRenderPass RenderPassBuilderVK::Build(
110 const vk::Device& device) const {
111 // This must be less than `VkPhysicalDeviceLimits::maxColorAttachments` but we
112 // are not checking.
113 auto color_attachments_count =
114 colors_.empty() ? 0u : colors_.rbegin()->first + 1u;
115 if (color0_.has_value()) {
116 color_attachments_count++;
117 }
118
119 std::array<vk::AttachmentDescription, kMaxAttachments> attachments;
120 std::array<vk::AttachmentReference, kMaxColorAttachments> color_refs;
121 std::array<vk::AttachmentReference, kMaxColorAttachments> resolve_refs;
122 vk::AttachmentReference depth_stencil_ref = kUnusedAttachmentReference;
123 size_t attachments_index = 0;
124 size_t color_index = 0;
125 size_t resolve_index = 0;
126
127 if (color0_.has_value()) {
128 vk::AttachmentReference color_ref;
129 color_ref.attachment = attachments_index;
130 color_ref.layout = vk::ImageLayout::eGeneral;
131 color_refs.at(color_index++) = color_ref;
132 attachments.at(attachments_index++) = color0_.value();
133
134 if (color0_resolve_.has_value()) {
135 vk::AttachmentReference resolve_ref;
136 resolve_ref.attachment = attachments_index;
137 resolve_ref.layout = vk::ImageLayout::eGeneral;
138 resolve_refs.at(resolve_index++) = resolve_ref;
139 attachments.at(attachments_index++) = color0_resolve_.value();
140 } else {
141 resolve_refs.at(resolve_index++) = kUnusedAttachmentReference;
142 }
143 }
144
145 for (const auto& color : colors_) {
146 vk::AttachmentReference color_ref;
147 color_ref.attachment = attachments_index;
148 color_ref.layout = vk::ImageLayout::eGeneral;
149 color_refs.at(color_index++) = color_ref;
150 attachments.at(attachments_index++) = color.second;
151
152 if (auto found = resolves_.find(color.first); found != resolves_.end()) {
153 vk::AttachmentReference resolve_ref;
154 resolve_ref.attachment = attachments_index;
155 resolve_ref.layout = vk::ImageLayout::eGeneral;
156 resolve_refs.at(resolve_index++) = resolve_ref;
157 attachments.at(attachments_index++) = found->second;
158 } else {
159 resolve_refs.at(resolve_index++) = kUnusedAttachmentReference;
160 }
161 }
162
163 if (depth_stencil_.has_value()) {
164 depth_stencil_ref.attachment = attachments_index;
165 depth_stencil_ref.layout = vk::ImageLayout::eGeneral;
166 attachments.at(attachments_index++) = depth_stencil_.value();
167 }
168
169 vk::SubpassDescription subpass0;
170 subpass0.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
171 subpass0.setPInputAttachments(color_refs.data());
172 subpass0.setInputAttachmentCount(color_index);
173 subpass0.setPColorAttachments(color_refs.data());
174 subpass0.setColorAttachmentCount(color_index);
175 subpass0.setPResolveAttachments(resolve_refs.data());
176
177 subpass0.setPDepthStencilAttachment(&depth_stencil_ref);
178
179 vk::SubpassDependency self_dep;
180 self_dep.srcSubpass = 0u; // first subpass
181 self_dep.dstSubpass = 0u; // to itself
182 self_dep.srcStageMask = kSelfDependencySrcStageMask;
183 self_dep.srcAccessMask = kSelfDependencySrcAccessMask;
184 self_dep.dstStageMask = kSelfDependencyDstStageMask;
185 self_dep.dstAccessMask = kSelfDependencyDstAccessMask;
186 self_dep.dependencyFlags = kSelfDependencyFlags;
187
188 vk::RenderPassCreateInfo render_pass_desc;
189 render_pass_desc.setPAttachments(attachments.data());
190 render_pass_desc.setAttachmentCount(attachments_index);
191 render_pass_desc.setSubpasses(subpass0);
192 render_pass_desc.setDependencies(self_dep);
193
194 auto [result, pass] = device.createRenderPassUnique(render_pass_desc);
195 if (result != vk::Result::eSuccess) {
196 VALIDATION_LOG << "Failed to create render pass: " << vk::to_string(result);
197 return {};
198 }
199 return std::move(pass);
200 }
201
202 void InsertBarrierForInputAttachmentRead(const vk::CommandBuffer& buffer,
203 const vk::Image& image) {
204 // This barrier must be a subset of the masks specified in the subpass
205 // dependency setup.
206 vk::ImageMemoryBarrier barrier;
207 barrier.srcAccessMask = kSelfDependencySrcAccessMask;
208 barrier.dstAccessMask = kSelfDependencyDstAccessMask;
209 barrier.oldLayout = vk::ImageLayout::eGeneral;
210 barrier.newLayout = vk::ImageLayout::eGeneral;
211 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
212 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
213 barrier.image = image;
214
215 vk::ImageSubresourceRange image_levels;
216 image_levels.aspectMask = vk::ImageAspectFlagBits::eColor;
217 image_levels.baseArrayLayer = 0u;
218 image_levels.baseMipLevel = 0u;
219 image_levels.layerCount = VK_REMAINING_ARRAY_LAYERS;
220 image_levels.levelCount = VK_REMAINING_MIP_LEVELS;
221 barrier.subresourceRange = image_levels;
222
223 buffer.pipelineBarrier(kSelfDependencySrcStageMask, //
224 kSelfDependencyDstStageMask, //
225 kSelfDependencyFlags, //
226 {}, //
227 {}, //
228 barrier //
229 );
230 }
231
232 const std::map<size_t, vk::AttachmentDescription>&
233 RenderPassBuilderVK::GetColorAttachments() const {
234 return colors_;
235 }
236
237 const std::map<size_t, vk::AttachmentDescription>&
238 RenderPassBuilderVK::GetResolves() const {
239 return resolves_;
240 }
241
242 const std::optional<vk::AttachmentDescription>&
243 RenderPassBuilderVK::GetDepthStencil() const {
244 return depth_stencil_;
245 }
246
247 // Visible for testing.
248 std::optional<vk::AttachmentDescription> RenderPassBuilderVK::GetColor0()
249 const {
250 return color0_;
251 }
252
253 // Visible for testing.
254 std::optional<vk::AttachmentDescription> RenderPassBuilderVK::GetColor0Resolve()
255 const {
256 return color0_resolve_;
257 }
258
259 } // namespace impeller
impeller::ToVKSampleCount
constexpr vk::SampleCountFlagBits ToVKSampleCount(SampleCount sample_count)
Definition: formats_vk.h:214
impeller::LoadAction::kLoad
@ kLoad
impeller::StoreAction
StoreAction
Definition: formats.h:208
impeller::kSelfDependencyDstAccessMask
constexpr auto kSelfDependencyDstAccessMask
Definition: render_pass_builder_vk.cc:19
impeller::RenderPassBuilderVK::SetStencilAttachment
RenderPassBuilderVK & SetStencilAttachment(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action)
Definition: render_pass_builder_vk.cc:91
impeller::kSelfDependencySrcStageMask
constexpr auto kSelfDependencySrcStageMask
Definition: render_pass_builder_vk.cc:12
formats.h
impeller::RenderPassBuilderVK
Definition: render_pass_builder_vk.h:21
formats_vk.h
impeller::kSelfDependencyFlags
constexpr auto kSelfDependencyFlags
Definition: render_pass_builder_vk.cc:22
impeller::RenderPassBuilderVK::GetColorAttachments
const std::map< size_t, vk::AttachmentDescription > & GetColorAttachments() const
Definition: render_pass_builder_vk.cc:233
impeller::ToVKAttachmentStoreOp
constexpr vk::AttachmentStoreOp ToVKAttachmentStoreOp(StoreAction store_action, bool is_resolve_texture)
Definition: formats_vk.h:319
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
impeller::RenderPassBuilderVK::SetDepthStencilAttachment
RenderPassBuilderVK & SetDepthStencilAttachment(PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action)
Definition: render_pass_builder_vk.cc:73
impeller::RenderPassBuilderVK::GetDepthStencil
const std::optional< vk::AttachmentDescription > & GetDepthStencil() const
Definition: render_pass_builder_vk.cc:243
impeller::RenderPassBuilderVK::SetColorAttachment
RenderPassBuilderVK & SetColorAttachment(size_t index, PixelFormat format, SampleCount sample_count, LoadAction load_action, StoreAction store_action, vk::ImageLayout current_layout=vk::ImageLayout::eUndefined)
Definition: render_pass_builder_vk.cc:28
impeller::ToVKImageFormat
constexpr vk::Format ToVKImageFormat(PixelFormat format)
Definition: formats_vk.h:146
impeller::RenderPassBuilderVK::RenderPassBuilderVK
RenderPassBuilderVK()
impeller::InsertBarrierForInputAttachmentRead
void InsertBarrierForInputAttachmentRead(const vk::CommandBuffer &buffer, const vk::Image &image)
Inserts the appropriate barriers to ensure that subsequent commands can read from the specified image...
Definition: render_pass_builder_vk.cc:202
impeller::LoadAction
LoadAction
Definition: formats.h:202
impeller::RenderPassBuilderVK::GetResolves
const std::map< size_t, vk::AttachmentDescription > & GetResolves() const
Definition: render_pass_builder_vk.cc:238
impeller::kSelfDependencyDstStageMask
constexpr auto kSelfDependencyDstStageMask
Definition: render_pass_builder_vk.cc:17
render_pass_builder_vk.h
impeller::RenderPassBuilderVK::GetColor0Resolve
std::optional< vk::AttachmentDescription > GetColor0Resolve() const
Definition: render_pass_builder_vk.cc:254
impeller::RenderPassBuilderVK::GetColor0
std::optional< vk::AttachmentDescription > GetColor0() const
Definition: render_pass_builder_vk.cc:248
impeller::RenderPassBuilderVK::~RenderPassBuilderVK
~RenderPassBuilderVK()
impeller::ToVKAttachmentLoadOp
constexpr vk::AttachmentLoadOp ToVKAttachmentLoadOp(LoadAction load_action)
Definition: formats_vk.h:306
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91
impeller::SampleCount
SampleCount
Definition: formats.h:295
impeller::kUnusedAttachmentReference
static constexpr vk::AttachmentReference kUnusedAttachmentReference
Definition: formats_vk.h:438
impeller::RenderPassBuilderVK::Build
vk::UniqueRenderPass Build(const vk::Device &device) const
Definition: render_pass_builder_vk.cc:109
impeller::kSelfDependencySrcAccessMask
constexpr auto kSelfDependencySrcAccessMask
Definition: render_pass_builder_vk.cc:14
impeller
Definition: allocation.cc:12
impeller::StoreActionPerformsResolve
constexpr bool StoreActionPerformsResolve(StoreAction store_action)
Definition: formats_vk.h:343