xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // RenderTargetVk:
7 //   Wrapper around a Vulkan renderable resource, using an ImageView.
8 //
9 
10 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
11 
12 #include "libANGLE/renderer/vulkan/ContextVk.h"
13 #include "libANGLE/renderer/vulkan/TextureVk.h"
14 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
15 #include "libANGLE/renderer/vulkan/vk_helpers.h"
16 #include "libANGLE/renderer/vulkan/vk_resource.h"
17 
18 namespace rx
19 {
20 
RenderTargetVk()21 RenderTargetVk::RenderTargetVk()
22 {
23     reset();
24 }
25 
~RenderTargetVk()26 RenderTargetVk::~RenderTargetVk()
27 {
28     ASSERT(mFramebufferCacheManager.empty());
29 }
30 
RenderTargetVk(RenderTargetVk && other)31 RenderTargetVk::RenderTargetVk(RenderTargetVk &&other)
32     : mImage(other.mImage),
33       mImageViews(other.mImageViews),
34       mResolveImage(other.mResolveImage),
35       mResolveImageViews(other.mResolveImageViews),
36       mImageSiblingSerial(other.mImageSiblingSerial),
37       mLevelIndexGL(other.mLevelIndexGL),
38       mLayerIndex(other.mLayerIndex),
39       mLayerCount(other.mLayerCount),
40       mFramebufferCacheManager(other.mFramebufferCacheManager)
41 {
42     other.reset();
43 }
44 
init(vk::ImageHelper * image,vk::ImageViewHelper * imageViews,vk::ImageHelper * resolveImage,vk::ImageViewHelper * resolveImageViews,UniqueSerial imageSiblingSerial,gl::LevelIndex levelIndexGL,uint32_t layerIndex,uint32_t layerCount,RenderTargetTransience transience)45 void RenderTargetVk::init(vk::ImageHelper *image,
46                           vk::ImageViewHelper *imageViews,
47                           vk::ImageHelper *resolveImage,
48                           vk::ImageViewHelper *resolveImageViews,
49                           UniqueSerial imageSiblingSerial,
50                           gl::LevelIndex levelIndexGL,
51                           uint32_t layerIndex,
52                           uint32_t layerCount,
53                           RenderTargetTransience transience)
54 {
55     mImage              = image;
56     mImageViews         = imageViews;
57     mResolveImage       = resolveImage;
58     mResolveImageViews  = resolveImageViews;
59     mImageSiblingSerial = imageSiblingSerial;
60     mLevelIndexGL       = levelIndexGL;
61     mLayerIndex         = layerIndex;
62     mLayerCount         = layerCount;
63 
64     mTransience = transience;
65 }
66 
invalidateImageAndViews()67 void RenderTargetVk::invalidateImageAndViews()
68 {
69     mImage             = nullptr;
70     mImageViews        = nullptr;
71     mResolveImage      = nullptr;
72     mResolveImageViews = nullptr;
73 }
74 
reset()75 void RenderTargetVk::reset()
76 {
77     invalidateImageAndViews();
78     mImageSiblingSerial = {};
79     mLevelIndexGL       = gl::LevelIndex(0);
80     mLayerIndex         = 0;
81     mLayerCount         = 0;
82 }
83 
getSubresourceSerialImpl(vk::ImageViewHelper * imageViews) const84 vk::ImageOrBufferViewSubresourceSerial RenderTargetVk::getSubresourceSerialImpl(
85     vk::ImageViewHelper *imageViews) const
86 {
87     ASSERT(imageViews);
88     ASSERT(mLayerIndex < std::numeric_limits<uint16_t>::max());
89     ASSERT(mLevelIndexGL.get() < std::numeric_limits<uint16_t>::max());
90 
91     vk::LayerMode layerMode = vk::GetLayerMode(*mImage, mLayerCount);
92     vk::ImageOrBufferViewSubresourceSerial imageViewSerial =
93         imageViews->getSubresourceSerial(mLevelIndexGL, 1, mLayerIndex, layerMode);
94     return imageViewSerial;
95 }
96 
getDrawSubresourceSerial() const97 vk::ImageOrBufferViewSubresourceSerial RenderTargetVk::getDrawSubresourceSerial() const
98 {
99     return getSubresourceSerialImpl(mImageViews);
100 }
101 
getResolveSubresourceSerial() const102 vk::ImageOrBufferViewSubresourceSerial RenderTargetVk::getResolveSubresourceSerial() const
103 {
104     return getSubresourceSerialImpl(mResolveImageViews);
105 }
106 
onColorDraw(ContextVk * contextVk,uint32_t framebufferLayerCount,vk::PackedAttachmentIndex packedAttachmentIndex)107 void RenderTargetVk::onColorDraw(ContextVk *contextVk,
108                                  uint32_t framebufferLayerCount,
109                                  vk::PackedAttachmentIndex packedAttachmentIndex)
110 {
111     ASSERT(!mImage->getActualFormat().hasDepthOrStencilBits());
112     ASSERT(framebufferLayerCount <= mLayerCount);
113 
114     contextVk->onColorDraw(mLevelIndexGL, mLayerIndex, framebufferLayerCount, mImage, mResolveImage,
115                            mImageSiblingSerial, packedAttachmentIndex);
116 
117     // Multisampled render to texture framebuffers cannot be layered.
118     ASSERT(mResolveImage == nullptr || framebufferLayerCount == 1);
119 }
120 
onColorResolve(ContextVk * contextVk,uint32_t framebufferLayerCount,size_t readColorIndexGL,const vk::ImageView & view)121 void RenderTargetVk::onColorResolve(ContextVk *contextVk,
122                                     uint32_t framebufferLayerCount,
123                                     size_t readColorIndexGL,
124                                     const vk::ImageView &view)
125 {
126     ASSERT(!mImage->getActualFormat().hasDepthOrStencilBits());
127     ASSERT(framebufferLayerCount <= mLayerCount);
128     ASSERT(mResolveImage == nullptr);
129 
130     // The currently open render pass is from the read framebuffer.  This is the draw framebuffer's
131     // render target.  Ask the context to add this image as the resolve attachment to the read
132     // framebuffer's render pass, at the given color index.
133     contextVk->onColorResolve(mLevelIndexGL, mLayerIndex, framebufferLayerCount, mImage,
134                               view.getHandle(), mImageSiblingSerial, readColorIndexGL);
135 }
136 
onDepthStencilDraw(ContextVk * contextVk,uint32_t framebufferLayerCount)137 void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk, uint32_t framebufferLayerCount)
138 {
139     const angle::Format &format = mImage->getActualFormat();
140     ASSERT(format.hasDepthOrStencilBits());
141     ASSERT(framebufferLayerCount <= mLayerCount);
142 
143     contextVk->onDepthStencilDraw(mLevelIndexGL, mLayerIndex, framebufferLayerCount, mImage,
144                                   mResolveImage, mImageSiblingSerial);
145 }
146 
onDepthStencilResolve(ContextVk * contextVk,uint32_t framebufferLayerCount,VkImageAspectFlags aspects,const vk::ImageView & view)147 void RenderTargetVk::onDepthStencilResolve(ContextVk *contextVk,
148                                            uint32_t framebufferLayerCount,
149                                            VkImageAspectFlags aspects,
150                                            const vk::ImageView &view)
151 {
152     ASSERT(mImage->getActualFormat().hasDepthOrStencilBits());
153     ASSERT(framebufferLayerCount <= mLayerCount);
154     ASSERT(mResolveImage == nullptr);
155 
156     contextVk->onDepthStencilResolve(mLevelIndexGL, mLayerIndex, framebufferLayerCount, aspects,
157                                      mImage, view.getHandle(), mImageSiblingSerial);
158 }
159 
getImageForRenderPass()160 vk::ImageHelper &RenderTargetVk::getImageForRenderPass()
161 {
162     ASSERT(mImage && mImage->valid());
163     return *mImage;
164 }
165 
getImageForRenderPass() const166 const vk::ImageHelper &RenderTargetVk::getImageForRenderPass() const
167 {
168     ASSERT(mImage && mImage->valid());
169     return *mImage;
170 }
171 
getResolveImageForRenderPass()172 vk::ImageHelper &RenderTargetVk::getResolveImageForRenderPass()
173 {
174     ASSERT(mResolveImage && mResolveImage->valid());
175     return *mResolveImage;
176 }
177 
getResolveImageForRenderPass() const178 const vk::ImageHelper &RenderTargetVk::getResolveImageForRenderPass() const
179 {
180     ASSERT(mResolveImage && mResolveImage->valid());
181     return *mResolveImage;
182 }
183 
getImageViewImpl(vk::Context * context,const vk::ImageHelper & image,vk::ImageViewHelper * imageViews,const vk::ImageView ** imageViewOut) const184 angle::Result RenderTargetVk::getImageViewImpl(vk::Context *context,
185                                                const vk::ImageHelper &image,
186                                                vk::ImageViewHelper *imageViews,
187                                                const vk::ImageView **imageViewOut) const
188 {
189     ASSERT(image.valid() && imageViews);
190     vk::LevelIndex levelVk = image.toVkLevel(getLevelIndexForImage(image));
191     if (mLayerCount == 1)
192     {
193         return imageViews->getLevelLayerDrawImageView(context, image, levelVk, mLayerIndex,
194                                                       imageViewOut);
195     }
196 
197     // Layered render targets view the whole level or a handful of layers in case of multiview.
198     return imageViews->getLevelDrawImageView(context, image, levelVk, mLayerIndex, mLayerCount,
199                                              imageViewOut);
200 }
201 
getImageView(vk::Context * context,const vk::ImageView ** imageViewOut) const202 angle::Result RenderTargetVk::getImageView(vk::Context *context,
203                                            const vk::ImageView **imageViewOut) const
204 {
205     ASSERT(mImage);
206     return getImageViewImpl(context, *mImage, mImageViews, imageViewOut);
207 }
208 
getImageViewWithColorspace(vk::Context * context,gl::SrgbWriteControlMode mode,const vk::ImageView ** imageViewOut) const209 angle::Result RenderTargetVk::getImageViewWithColorspace(vk::Context *context,
210                                                          gl::SrgbWriteControlMode mode,
211                                                          const vk::ImageView **imageViewOut) const
212 {
213     ASSERT(mImage);
214     mImageViews->updateSrgbWiteControlMode(*mImage, mode);
215     return getImageViewImpl(context, *mImage, mImageViews, imageViewOut);
216 }
217 
getResolveImageView(vk::Context * context,const vk::ImageView ** imageViewOut) const218 angle::Result RenderTargetVk::getResolveImageView(vk::Context *context,
219                                                   const vk::ImageView **imageViewOut) const
220 {
221     ASSERT(mResolveImage);
222     return getImageViewImpl(context, *mResolveImage, mResolveImageViews, imageViewOut);
223 }
224 
getDepthOrStencilImageView(vk::Context * context,VkImageAspectFlagBits aspect,const vk::ImageView ** imageViewOut) const225 angle::Result RenderTargetVk::getDepthOrStencilImageView(vk::Context *context,
226                                                          VkImageAspectFlagBits aspect,
227                                                          const vk::ImageView **imageViewOut) const
228 {
229     ASSERT(mImage);
230     return getDepthOrStencilImageViewImpl(context, *mImage, mImageViews, aspect, imageViewOut);
231 }
232 
getDepthOrStencilImageViewForCopy(vk::Context * context,VkImageAspectFlagBits aspect,const vk::ImageView ** imageViewOut) const233 angle::Result RenderTargetVk::getDepthOrStencilImageViewForCopy(
234     vk::Context *context,
235     VkImageAspectFlagBits aspect,
236     const vk::ImageView **imageViewOut) const
237 {
238     return isResolveImageOwnerOfData()
239                ? getResolveDepthOrStencilImageView(context, aspect, imageViewOut)
240                : getDepthOrStencilImageView(context, aspect, imageViewOut);
241 }
242 
getResolveDepthOrStencilImageView(vk::Context * context,VkImageAspectFlagBits aspect,const vk::ImageView ** imageViewOut) const243 angle::Result RenderTargetVk::getResolveDepthOrStencilImageView(
244     vk::Context *context,
245     VkImageAspectFlagBits aspect,
246     const vk::ImageView **imageViewOut) const
247 {
248     ASSERT(mResolveImage);
249     return getDepthOrStencilImageViewImpl(context, *mResolveImage, mResolveImageViews, aspect,
250                                           imageViewOut);
251 }
252 
getDepthOrStencilImageViewImpl(vk::Context * context,const vk::ImageHelper & image,vk::ImageViewHelper * imageViews,VkImageAspectFlagBits aspect,const vk::ImageView ** imageViewOut) const253 angle::Result RenderTargetVk::getDepthOrStencilImageViewImpl(
254     vk::Context *context,
255     const vk::ImageHelper &image,
256     vk::ImageViewHelper *imageViews,
257     VkImageAspectFlagBits aspect,
258     const vk::ImageView **imageViewOut) const
259 {
260     // If the image has only one aspect, the usual view is sufficient.
261     if (image.getAspectFlags() == aspect)
262     {
263         return getImageViewImpl(context, image, imageViews, imageViewOut);
264     }
265 
266     // Otherwise, for images with both the depth and stencil aspects, need to create special views
267     // that select only one such aspect.
268     ASSERT(image.valid() && imageViews);
269     vk::LevelIndex levelVk = image.toVkLevel(getLevelIndexForImage(image));
270     if (mLayerCount == 1)
271     {
272         return imageViews->getLevelLayerDepthOrStencilImageView(context, image, levelVk,
273                                                                 mLayerIndex, aspect, imageViewOut);
274     }
275 
276     // Layered render targets view the whole level or a handful of layers in case of multiview.
277     return imageViews->getLevelDepthOrStencilImageView(context, image, levelVk, mLayerIndex,
278                                                        mLayerCount, aspect, imageViewOut);
279 }
280 
isResolveImageOwnerOfData() const281 bool RenderTargetVk::isResolveImageOwnerOfData() const
282 {
283     // If there's a resolve attachment and the image itself is transient, it's the resolve
284     // attachment that owns the data, so all non-render-pass accesses to the render target data
285     // should go through the resolve attachment.
286     return isImageTransient();
287 }
288 
getOwnerOfData() const289 vk::ImageHelper *RenderTargetVk::getOwnerOfData() const
290 {
291     return isResolveImageOwnerOfData() ? mResolveImage : mImage;
292 }
293 
getCopyImageView(vk::Context * context,const vk::ImageView ** imageViewOut) const294 angle::Result RenderTargetVk::getCopyImageView(vk::Context *context,
295                                                const vk::ImageView **imageViewOut) const
296 {
297     const vk::ImageViewHelper *imageViews =
298         isResolveImageOwnerOfData() ? mResolveImageViews : mImageViews;
299 
300     // If the source of render target is a texture or renderbuffer, this will always be valid.  This
301     // is also where 3D or 2DArray images could be the source of the render target.
302     if (imageViews->hasCopyImageView())
303     {
304         *imageViewOut = &imageViews->getCopyImageView();
305         return angle::Result::Continue;
306     }
307 
308     // Otherwise, this must come from the surface, in which case the image is 2D, so the image view
309     // used to draw is just as good for fetching.  If resolve attachment is present, fetching is
310     // done from that.
311     return isResolveImageOwnerOfData() ? getResolveImageView(context, imageViewOut)
312                                        : getImageView(context, imageViewOut);
313 }
314 
getImageActualFormatID() const315 angle::FormatID RenderTargetVk::getImageActualFormatID() const
316 {
317     ASSERT(mImage && mImage->valid());
318     return mImage->getActualFormatID();
319 }
320 
getImageIntendedFormatID() const321 angle::FormatID RenderTargetVk::getImageIntendedFormatID() const
322 {
323     ASSERT(mImage && mImage->valid());
324     return mImage->getIntendedFormatID();
325 }
326 
getImageActualFormat() const327 const angle::Format &RenderTargetVk::getImageActualFormat() const
328 {
329     ASSERT(mImage && mImage->valid());
330     return mImage->getActualFormat();
331 }
332 
getImageIntendedFormat() const333 const angle::Format &RenderTargetVk::getImageIntendedFormat() const
334 {
335     ASSERT(mImage && mImage->valid());
336     return mImage->getIntendedFormat();
337 }
338 
getExtents() const339 gl::Extents RenderTargetVk::getExtents() const
340 {
341     ASSERT(mImage && mImage->valid());
342     vk::LevelIndex levelVk = mImage->toVkLevel(mLevelIndexGL);
343     return mImage->getLevelExtents2D(levelVk);
344 }
345 
getRotatedExtents() const346 gl::Extents RenderTargetVk::getRotatedExtents() const
347 {
348     ASSERT(mImage && mImage->valid());
349     vk::LevelIndex levelVk = mImage->toVkLevel(mLevelIndexGL);
350     return mImage->getRotatedLevelExtents2D(levelVk);
351 }
352 
getLevelIndexForImage(const vk::ImageHelper & image) const353 gl::LevelIndex RenderTargetVk::getLevelIndexForImage(const vk::ImageHelper &image) const
354 {
355     return (getOwnerOfData()->getImageSerial() == image.getImageSerial()) ? mLevelIndexGL
356                                                                           : gl::LevelIndex(0);
357 }
358 
updateSwapchainImage(vk::ImageHelper * image,vk::ImageViewHelper * imageViews,vk::ImageHelper * resolveImage,vk::ImageViewHelper * resolveImageViews)359 void RenderTargetVk::updateSwapchainImage(vk::ImageHelper *image,
360                                           vk::ImageViewHelper *imageViews,
361                                           vk::ImageHelper *resolveImage,
362                                           vk::ImageViewHelper *resolveImageViews)
363 {
364     ASSERT(image && image->valid() && imageViews);
365     mImage             = image;
366     mImageViews        = imageViews;
367     mResolveImage      = resolveImage;
368     mResolveImageViews = resolveImageViews;
369 }
370 
getImageForCopy() const371 vk::ImageHelper &RenderTargetVk::getImageForCopy() const
372 {
373     ASSERT(mImage && mImage->valid() && (mResolveImage == nullptr || mResolveImage->valid()));
374     return *getOwnerOfData();
375 }
376 
getImageForWrite() const377 vk::ImageHelper &RenderTargetVk::getImageForWrite() const
378 {
379     ASSERT(mImage && mImage->valid() && (mResolveImage == nullptr || mResolveImage->valid()));
380     return *getOwnerOfData();
381 }
382 
flushStagedUpdates(ContextVk * contextVk,vk::ClearValuesArray * deferredClears,uint32_t deferredClearIndex,uint32_t framebufferLayerCount)383 angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk,
384                                                  vk::ClearValuesArray *deferredClears,
385                                                  uint32_t deferredClearIndex,
386                                                  uint32_t framebufferLayerCount)
387 {
388     ASSERT(mImage->valid() && (!isResolveImageOwnerOfData() || mResolveImage->valid()));
389     ASSERT(framebufferLayerCount != 0);
390 
391     // It's impossible to defer clears to slices of a 3D images, as the clear applies to all the
392     // slices, while deferred clears only clear a single slice (where the framebuffer is attached).
393     // Additionally, the layer index for 3D textures is always zero according to Vulkan.
394     uint32_t layerIndex = mLayerIndex;
395     if (mImage->getType() == VK_IMAGE_TYPE_3D)
396     {
397         layerIndex         = 0;
398         deferredClears     = nullptr;
399         deferredClearIndex = 0;
400     }
401 
402     vk::ImageHelper *image = getOwnerOfData();
403 
404     // All updates should be staged on the image that owns the data as the source of truth.  With
405     // multisampled-render-to-texture framebuffers, that is the resolve image.  In that case, even
406     // though deferred clears set the loadOp of the transient multisampled image, the clears
407     // themselves are staged on the resolve image.  The |flushSingleSubresourceStagedUpdates| call
408     // below will either flush all staged updates to the resolve image, or if the only staged update
409     // is a clear, it will accumulate it in the |deferredClears| array.  Later, when the render pass
410     // is started, the deferred clears are applied to the transient multisampled image.
411     ASSERT(!isResolveImageOwnerOfData() ||
412            !mImage->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, mLayerCount));
413     ASSERT(isResolveImageOwnerOfData() || mResolveImage == nullptr ||
414            !mResolveImage->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, mLayerCount));
415 
416     if (!image->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, framebufferLayerCount))
417     {
418         return angle::Result::Continue;
419     }
420 
421     return image->flushSingleSubresourceStagedUpdates(contextVk, mLevelIndexGL, layerIndex,
422                                                       framebufferLayerCount, deferredClears,
423                                                       deferredClearIndex);
424 }
425 
hasDefinedContent() const426 bool RenderTargetVk::hasDefinedContent() const
427 {
428     vk::ImageHelper *image = getOwnerOfData();
429     return image->hasSubresourceDefinedContent(mLevelIndexGL, mLayerIndex, mLayerCount);
430 }
431 
hasDefinedStencilContent() const432 bool RenderTargetVk::hasDefinedStencilContent() const
433 {
434     vk::ImageHelper *image = getOwnerOfData();
435     return image->hasSubresourceDefinedStencilContent(mLevelIndexGL, mLayerIndex, mLayerCount);
436 }
437 
invalidateEntireContent(ContextVk * contextVk,bool * preferToKeepContentsDefinedOut)438 void RenderTargetVk::invalidateEntireContent(ContextVk *contextVk,
439                                              bool *preferToKeepContentsDefinedOut)
440 {
441     vk::ImageHelper *image = getOwnerOfData();
442     image->invalidateSubresourceContent(contextVk, mLevelIndexGL, mLayerIndex, mLayerCount,
443                                         preferToKeepContentsDefinedOut);
444 }
445 
invalidateEntireStencilContent(ContextVk * contextVk,bool * preferToKeepContentsDefinedOut)446 void RenderTargetVk::invalidateEntireStencilContent(ContextVk *contextVk,
447                                                     bool *preferToKeepContentsDefinedOut)
448 {
449     vk::ImageHelper *image = getOwnerOfData();
450     image->invalidateSubresourceStencilContent(contextVk, mLevelIndexGL, mLayerIndex, mLayerCount,
451                                                preferToKeepContentsDefinedOut);
452 }
453 
getImageIndexForClear(uint32_t layerCount) const454 gl::ImageIndex RenderTargetVk::getImageIndexForClear(uint32_t layerCount) const
455 {
456     // Determine the GL type from the Vk Image properties.
457     if (mImage->getType() == VK_IMAGE_TYPE_3D || mImage->getLayerCount() > 1)
458     {
459         // This is used for the sake of staging clears.  The depth slices of the 3D image are
460         // threated as layers for this purpose.
461         //
462         // We also don't need to distinguish 2D array and cube.
463         return gl::ImageIndex::Make2DArrayRange(mLevelIndexGL.get(), mLayerIndex, layerCount);
464     }
465 
466     ASSERT(mLayerIndex == 0);
467     ASSERT(mLayerCount == 1);
468     ASSERT(layerCount == 1);
469     return gl::ImageIndex::Make2D(mLevelIndexGL.get());
470 }
471 }  // namespace rx
472