• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
reset()67 void RenderTargetVk::reset()
68 {
69     mImage              = nullptr;
70     mImageViews         = nullptr;
71     mResolveImage       = nullptr;
72     mResolveImageViews  = nullptr;
73     mImageSiblingSerial = {};
74     mLevelIndexGL       = gl::LevelIndex(0);
75     mLayerIndex         = 0;
76     mLayerCount         = 0;
77 }
78 
getSubresourceSerialImpl(vk::ImageViewHelper * imageViews) const79 vk::ImageOrBufferViewSubresourceSerial RenderTargetVk::getSubresourceSerialImpl(
80     vk::ImageViewHelper *imageViews) const
81 {
82     ASSERT(imageViews);
83     ASSERT(mLayerIndex < std::numeric_limits<uint16_t>::max());
84     ASSERT(mLevelIndexGL.get() < std::numeric_limits<uint16_t>::max());
85 
86     vk::LayerMode layerMode = vk::GetLayerMode(*mImage, mLayerCount);
87     vk::ImageOrBufferViewSubresourceSerial imageViewSerial =
88         imageViews->getSubresourceSerial(mLevelIndexGL, 1, mLayerIndex, layerMode);
89     return imageViewSerial;
90 }
91 
getDrawSubresourceSerial() const92 vk::ImageOrBufferViewSubresourceSerial RenderTargetVk::getDrawSubresourceSerial() const
93 {
94     return getSubresourceSerialImpl(mImageViews);
95 }
96 
getResolveSubresourceSerial() const97 vk::ImageOrBufferViewSubresourceSerial RenderTargetVk::getResolveSubresourceSerial() const
98 {
99     return getSubresourceSerialImpl(mResolveImageViews);
100 }
101 
onColorDraw(ContextVk * contextVk,uint32_t framebufferLayerCount,vk::PackedAttachmentIndex packedAttachmentIndex)102 void RenderTargetVk::onColorDraw(ContextVk *contextVk,
103                                  uint32_t framebufferLayerCount,
104                                  vk::PackedAttachmentIndex packedAttachmentIndex)
105 {
106     ASSERT(!mImage->getActualFormat().hasDepthOrStencilBits());
107     ASSERT(framebufferLayerCount <= mLayerCount);
108 
109     contextVk->onColorDraw(mLevelIndexGL, mLayerIndex, framebufferLayerCount, mImage, mResolveImage,
110                            mImageSiblingSerial, packedAttachmentIndex);
111 
112     // Multisampled render to texture framebuffers cannot be layered.
113     ASSERT(mResolveImage == nullptr || framebufferLayerCount == 1);
114 }
115 
onColorResolve(ContextVk * contextVk,uint32_t framebufferLayerCount,size_t readColorIndexGL,const vk::ImageView & view)116 void RenderTargetVk::onColorResolve(ContextVk *contextVk,
117                                     uint32_t framebufferLayerCount,
118                                     size_t readColorIndexGL,
119                                     const vk::ImageView &view)
120 {
121     ASSERT(!mImage->getActualFormat().hasDepthOrStencilBits());
122     ASSERT(framebufferLayerCount <= mLayerCount);
123     ASSERT(mResolveImage == nullptr);
124 
125     // The currently open render pass is from the read framebuffer.  This is the draw framebuffer's
126     // render target.  Ask the context to add this image as the resolve attachment to the read
127     // framebuffer's render pass, at the given color index.
128     contextVk->onColorResolve(mLevelIndexGL, mLayerIndex, framebufferLayerCount, mImage,
129                               view.getHandle(), mImageSiblingSerial, readColorIndexGL);
130 }
131 
onDepthStencilDraw(ContextVk * contextVk,uint32_t framebufferLayerCount)132 void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk, uint32_t framebufferLayerCount)
133 {
134     const angle::Format &format = mImage->getActualFormat();
135     ASSERT(format.hasDepthOrStencilBits());
136     ASSERT(framebufferLayerCount <= mLayerCount);
137 
138     contextVk->onDepthStencilDraw(mLevelIndexGL, mLayerIndex, framebufferLayerCount, mImage,
139                                   mResolveImage, mImageSiblingSerial);
140 }
141 
onDepthStencilResolve(ContextVk * contextVk,uint32_t framebufferLayerCount,VkImageAspectFlags aspects,const vk::ImageView & view)142 void RenderTargetVk::onDepthStencilResolve(ContextVk *contextVk,
143                                            uint32_t framebufferLayerCount,
144                                            VkImageAspectFlags aspects,
145                                            const vk::ImageView &view)
146 {
147     ASSERT(mImage->getActualFormat().hasDepthOrStencilBits());
148     ASSERT(framebufferLayerCount <= mLayerCount);
149     ASSERT(mResolveImage == nullptr);
150 
151     contextVk->onDepthStencilResolve(mLevelIndexGL, mLayerIndex, framebufferLayerCount, aspects,
152                                      mImage, view.getHandle(), mImageSiblingSerial);
153 }
154 
getImageForRenderPass()155 vk::ImageHelper &RenderTargetVk::getImageForRenderPass()
156 {
157     ASSERT(mImage && mImage->valid());
158     return *mImage;
159 }
160 
getImageForRenderPass() const161 const vk::ImageHelper &RenderTargetVk::getImageForRenderPass() const
162 {
163     ASSERT(mImage && mImage->valid());
164     return *mImage;
165 }
166 
getResolveImageForRenderPass()167 vk::ImageHelper &RenderTargetVk::getResolveImageForRenderPass()
168 {
169     ASSERT(mResolveImage && mResolveImage->valid());
170     return *mResolveImage;
171 }
172 
getResolveImageForRenderPass() const173 const vk::ImageHelper &RenderTargetVk::getResolveImageForRenderPass() const
174 {
175     ASSERT(mResolveImage && mResolveImage->valid());
176     return *mResolveImage;
177 }
178 
getImageViewImpl(vk::ErrorContext * context,const vk::ImageHelper & image,vk::ImageViewHelper * imageViews,const vk::ImageView ** imageViewOut) const179 angle::Result RenderTargetVk::getImageViewImpl(vk::ErrorContext *context,
180                                                const vk::ImageHelper &image,
181                                                vk::ImageViewHelper *imageViews,
182                                                const vk::ImageView **imageViewOut) const
183 {
184     ASSERT(image.valid() && imageViews);
185     vk::LevelIndex levelVk = image.toVkLevel(getLevelIndexForImage(image));
186     if (mLayerCount == 1)
187     {
188         return imageViews->getLevelLayerDrawImageView(context, image, levelVk, mLayerIndex,
189                                                       imageViewOut);
190     }
191 
192     // Layered render targets view the whole level or a handful of layers in case of multiview.
193     return imageViews->getLevelDrawImageView(context, image, levelVk, mLayerIndex, mLayerCount,
194                                              imageViewOut);
195 }
196 
getImageView(vk::ErrorContext * context,const vk::ImageView ** imageViewOut) const197 angle::Result RenderTargetVk::getImageView(vk::ErrorContext *context,
198                                            const vk::ImageView **imageViewOut) const
199 {
200     ASSERT(mImage);
201     return getImageViewImpl(context, *mImage, mImageViews, imageViewOut);
202 }
203 
getImageViewWithColorspace(vk::ErrorContext * context,gl::SrgbWriteControlMode mode,const vk::ImageView ** imageViewOut) const204 angle::Result RenderTargetVk::getImageViewWithColorspace(vk::ErrorContext *context,
205                                                          gl::SrgbWriteControlMode mode,
206                                                          const vk::ImageView **imageViewOut) const
207 {
208     ASSERT(mImage);
209     mImageViews->updateSrgbWiteControlMode(*mImage, mode);
210     return getImageViewImpl(context, *mImage, mImageViews, imageViewOut);
211 }
212 
getResolveImageView(vk::ErrorContext * context,const vk::ImageView ** imageViewOut) const213 angle::Result RenderTargetVk::getResolveImageView(vk::ErrorContext *context,
214                                                   const vk::ImageView **imageViewOut) const
215 {
216     ASSERT(mResolveImage);
217     return getImageViewImpl(context, *mResolveImage, mResolveImageViews, imageViewOut);
218 }
219 
getDepthOrStencilImageView(vk::ErrorContext * context,VkImageAspectFlagBits aspect,const vk::ImageView ** imageViewOut) const220 angle::Result RenderTargetVk::getDepthOrStencilImageView(vk::ErrorContext *context,
221                                                          VkImageAspectFlagBits aspect,
222                                                          const vk::ImageView **imageViewOut) const
223 {
224     ASSERT(mImage);
225     return getDepthOrStencilImageViewImpl(context, *mImage, mImageViews, aspect, imageViewOut);
226 }
227 
getDepthOrStencilImageViewForCopy(vk::ErrorContext * context,VkImageAspectFlagBits aspect,const vk::ImageView ** imageViewOut) const228 angle::Result RenderTargetVk::getDepthOrStencilImageViewForCopy(
229     vk::ErrorContext *context,
230     VkImageAspectFlagBits aspect,
231     const vk::ImageView **imageViewOut) const
232 {
233     return isResolveImageOwnerOfData()
234                ? getResolveDepthOrStencilImageView(context, aspect, imageViewOut)
235                : getDepthOrStencilImageView(context, aspect, imageViewOut);
236 }
237 
getResolveDepthOrStencilImageView(vk::ErrorContext * context,VkImageAspectFlagBits aspect,const vk::ImageView ** imageViewOut) const238 angle::Result RenderTargetVk::getResolveDepthOrStencilImageView(
239     vk::ErrorContext *context,
240     VkImageAspectFlagBits aspect,
241     const vk::ImageView **imageViewOut) const
242 {
243     ASSERT(mResolveImage);
244     return getDepthOrStencilImageViewImpl(context, *mResolveImage, mResolveImageViews, aspect,
245                                           imageViewOut);
246 }
247 
getDepthOrStencilImageViewImpl(vk::ErrorContext * context,const vk::ImageHelper & image,vk::ImageViewHelper * imageViews,VkImageAspectFlagBits aspect,const vk::ImageView ** imageViewOut) const248 angle::Result RenderTargetVk::getDepthOrStencilImageViewImpl(
249     vk::ErrorContext *context,
250     const vk::ImageHelper &image,
251     vk::ImageViewHelper *imageViews,
252     VkImageAspectFlagBits aspect,
253     const vk::ImageView **imageViewOut) const
254 {
255     // If the image has only one aspect, the usual view is sufficient.
256     if (image.getAspectFlags() == aspect)
257     {
258         return getImageViewImpl(context, image, imageViews, imageViewOut);
259     }
260 
261     // Otherwise, for images with both the depth and stencil aspects, need to create special views
262     // that select only one such aspect.
263     ASSERT(image.valid() && imageViews);
264     vk::LevelIndex levelVk = image.toVkLevel(getLevelIndexForImage(image));
265     if (mLayerCount == 1)
266     {
267         return imageViews->getLevelLayerDepthOrStencilImageView(context, image, levelVk,
268                                                                 mLayerIndex, aspect, imageViewOut);
269     }
270 
271     // Layered render targets view the whole level or a handful of layers in case of multiview.
272     return imageViews->getLevelDepthOrStencilImageView(context, image, levelVk, mLayerIndex,
273                                                        mLayerCount, aspect, imageViewOut);
274 }
275 
isResolveImageOwnerOfData() const276 bool RenderTargetVk::isResolveImageOwnerOfData() const
277 {
278     // If there's a resolve attachment and the image itself is transient, it's the resolve
279     // attachment that owns the data, so all non-render-pass accesses to the render target data
280     // should go through the resolve attachment.
281     return isImageTransient();
282 }
283 
getOwnerOfData() const284 vk::ImageHelper *RenderTargetVk::getOwnerOfData() const
285 {
286     return isResolveImageOwnerOfData() ? mResolveImage : mImage;
287 }
288 
getCopyImageView(vk::ErrorContext * context,const vk::ImageView ** imageViewOut) const289 angle::Result RenderTargetVk::getCopyImageView(vk::ErrorContext *context,
290                                                const vk::ImageView **imageViewOut) const
291 {
292     const vk::ImageViewHelper *imageViews =
293         isResolveImageOwnerOfData() ? mResolveImageViews : mImageViews;
294 
295     // If the source of render target is a texture or renderbuffer, this will always be valid.  This
296     // is also where 3D or 2DArray images could be the source of the render target.
297     if (imageViews->hasCopyImageView())
298     {
299         *imageViewOut = &imageViews->getCopyImageView();
300         return angle::Result::Continue;
301     }
302 
303     // Otherwise, this must come from the surface, in which case the image is 2D, so the image view
304     // used to draw is just as good for fetching.  If resolve attachment is present, fetching is
305     // done from that.
306     return isResolveImageOwnerOfData() ? getResolveImageView(context, imageViewOut)
307                                        : getImageView(context, imageViewOut);
308 }
309 
getImageActualFormatID() const310 angle::FormatID RenderTargetVk::getImageActualFormatID() const
311 {
312     ASSERT(mImage && mImage->valid());
313     return mImage->getActualFormatID();
314 }
315 
getImageIntendedFormatID() const316 angle::FormatID RenderTargetVk::getImageIntendedFormatID() const
317 {
318     ASSERT(mImage && mImage->valid());
319     return mImage->getIntendedFormatID();
320 }
321 
getImageActualFormat() const322 const angle::Format &RenderTargetVk::getImageActualFormat() const
323 {
324     ASSERT(mImage && mImage->valid());
325     return mImage->getActualFormat();
326 }
327 
getImageIntendedFormat() const328 const angle::Format &RenderTargetVk::getImageIntendedFormat() const
329 {
330     ASSERT(mImage && mImage->valid());
331     return mImage->getIntendedFormat();
332 }
333 
getExtents() const334 gl::Extents RenderTargetVk::getExtents() const
335 {
336     ASSERT(mImage && mImage->valid());
337     vk::LevelIndex levelVk = mImage->toVkLevel(mLevelIndexGL);
338     return mImage->getLevelExtents2D(levelVk);
339 }
340 
getRotatedExtents() const341 gl::Extents RenderTargetVk::getRotatedExtents() const
342 {
343     ASSERT(mImage && mImage->valid());
344     vk::LevelIndex levelVk = mImage->toVkLevel(mLevelIndexGL);
345     return mImage->getRotatedLevelExtents2D(levelVk);
346 }
347 
getLevelIndexForImage(const vk::ImageHelper & image) const348 gl::LevelIndex RenderTargetVk::getLevelIndexForImage(const vk::ImageHelper &image) const
349 {
350     return (getOwnerOfData()->getImageSerial() == image.getImageSerial()) ? mLevelIndexGL
351                                                                           : gl::LevelIndex(0);
352 }
353 
updateSwapchainImage(vk::ImageHelper * image,vk::ImageViewHelper * imageViews,vk::ImageHelper * resolveImage,vk::ImageViewHelper * resolveImageViews)354 void RenderTargetVk::updateSwapchainImage(vk::ImageHelper *image,
355                                           vk::ImageViewHelper *imageViews,
356                                           vk::ImageHelper *resolveImage,
357                                           vk::ImageViewHelper *resolveImageViews)
358 {
359     ASSERT(image && image->valid() && imageViews);
360     ASSERT(!mImageSiblingSerial.valid());
361     ASSERT(mLevelIndexGL == gl::LevelIndex(0));
362     ASSERT(mLayerIndex == 0);
363     mImage             = image;
364     mImageViews        = imageViews;
365     mResolveImage      = resolveImage;
366     mResolveImageViews = resolveImageViews;
367     mLayerCount        = 1;
368 }
369 
getImageForCopy() const370 vk::ImageHelper &RenderTargetVk::getImageForCopy() const
371 {
372     ASSERT(mImage && mImage->valid() && (mResolveImage == nullptr || mResolveImage->valid()));
373     return *getOwnerOfData();
374 }
375 
getImageForWrite() const376 vk::ImageHelper &RenderTargetVk::getImageForWrite() const
377 {
378     ASSERT(mImage && mImage->valid() && (mResolveImage == nullptr || mResolveImage->valid()));
379     return *getOwnerOfData();
380 }
381 
flushStagedUpdates(ContextVk * contextVk,vk::ClearValuesArray * deferredClears,uint32_t deferredClearIndex,uint32_t framebufferLayerCount)382 angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk,
383                                                  vk::ClearValuesArray *deferredClears,
384                                                  uint32_t deferredClearIndex,
385                                                  uint32_t framebufferLayerCount)
386 {
387     ASSERT(mImage->valid() && (!isResolveImageOwnerOfData() || mResolveImage->valid()));
388     ASSERT(framebufferLayerCount != 0);
389 
390     // It's impossible to defer clears to slices of a 3D images, as the clear applies to all the
391     // slices, while deferred clears only clear a single slice (where the framebuffer is attached).
392     // Additionally, the layer index for 3D textures is always zero according to Vulkan.
393     uint32_t layerIndex = mLayerIndex;
394     if (mImage->getType() == VK_IMAGE_TYPE_3D)
395     {
396         layerIndex         = 0;
397         deferredClears     = nullptr;
398         deferredClearIndex = 0;
399     }
400 
401     vk::ImageHelper *image = getOwnerOfData();
402 
403     // All updates should be staged on the image that owns the data as the source of truth.  With
404     // multisampled-render-to-texture framebuffers, that is the resolve image.  In that case, even
405     // though deferred clears set the loadOp of the transient multisampled image, the clears
406     // themselves are staged on the resolve image.  The |flushSingleSubresourceStagedUpdates| call
407     // below will either flush all staged updates to the resolve image, or if the only staged update
408     // is a clear, it will accumulate it in the |deferredClears| array.  Later, when the render pass
409     // is started, the deferred clears are applied to the transient multisampled image.
410     ASSERT(!isResolveImageOwnerOfData() ||
411            !mImage->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, mLayerCount));
412     ASSERT(isResolveImageOwnerOfData() || mResolveImage == nullptr ||
413            !mResolveImage->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, mLayerCount));
414 
415     if (!image->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, framebufferLayerCount))
416     {
417         return angle::Result::Continue;
418     }
419 
420     return image->flushSingleSubresourceStagedUpdates(contextVk, mLevelIndexGL, layerIndex,
421                                                       framebufferLayerCount, deferredClears,
422                                                       deferredClearIndex);
423 }
424 
hasDefinedContent() const425 bool RenderTargetVk::hasDefinedContent() const
426 {
427     vk::ImageHelper *image = getOwnerOfData();
428     return image->hasSubresourceDefinedContent(mLevelIndexGL, mLayerIndex, mLayerCount);
429 }
430 
hasDefinedStencilContent() const431 bool RenderTargetVk::hasDefinedStencilContent() const
432 {
433     vk::ImageHelper *image = getOwnerOfData();
434     return image->hasSubresourceDefinedStencilContent(mLevelIndexGL, mLayerIndex, mLayerCount);
435 }
436 
invalidateEntireContent(ContextVk * contextVk,bool * preferToKeepContentsDefinedOut)437 void RenderTargetVk::invalidateEntireContent(ContextVk *contextVk,
438                                              bool *preferToKeepContentsDefinedOut)
439 {
440     vk::ImageHelper *image = getOwnerOfData();
441     image->invalidateSubresourceContent(contextVk, mLevelIndexGL, mLayerIndex, mLayerCount,
442                                         preferToKeepContentsDefinedOut);
443 }
444 
invalidateEntireStencilContent(ContextVk * contextVk,bool * preferToKeepContentsDefinedOut)445 void RenderTargetVk::invalidateEntireStencilContent(ContextVk *contextVk,
446                                                     bool *preferToKeepContentsDefinedOut)
447 {
448     vk::ImageHelper *image = getOwnerOfData();
449     image->invalidateSubresourceStencilContent(contextVk, mLevelIndexGL, mLayerIndex, mLayerCount,
450                                                preferToKeepContentsDefinedOut);
451 }
452 
getImageIndexForClear(uint32_t layerCount) const453 gl::ImageIndex RenderTargetVk::getImageIndexForClear(uint32_t layerCount) const
454 {
455     // Determine the GL type from the Vk Image properties.
456     if (mImage->getType() == VK_IMAGE_TYPE_3D || mImage->getLayerCount() > 1)
457     {
458         // This is used for the sake of staging clears.  The depth slices of the 3D image are
459         // threated as layers for this purpose.
460         //
461         // We also don't need to distinguish 2D array and cube.
462         return gl::ImageIndex::Make2DArrayRange(mLevelIndexGL.get(), mLayerIndex, layerCount);
463     }
464 
465     ASSERT(mLayerIndex == 0);
466     ASSERT(mLayerCount == 1);
467     ASSERT(layerCount == 1);
468     return gl::ImageIndex::Make2D(mLevelIndexGL.get());
469 }
470 }  // namespace rx
471