• 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                                          vk::SrgbDecodeMode::SkipDecode, gl::SrgbOverride::Default);
90     return imageViewSerial;
91 }
92 
getDrawSubresourceSerial() const93 vk::ImageOrBufferViewSubresourceSerial RenderTargetVk::getDrawSubresourceSerial() const
94 {
95     return getSubresourceSerialImpl(mImageViews);
96 }
97 
getResolveSubresourceSerial() const98 vk::ImageOrBufferViewSubresourceSerial RenderTargetVk::getResolveSubresourceSerial() const
99 {
100     return getSubresourceSerialImpl(mResolveImageViews);
101 }
102 
onColorDraw(ContextVk * contextVk,uint32_t framebufferLayerCount,vk::PackedAttachmentIndex packedAttachmentIndex)103 void RenderTargetVk::onColorDraw(ContextVk *contextVk,
104                                  uint32_t framebufferLayerCount,
105                                  vk::PackedAttachmentIndex packedAttachmentIndex)
106 {
107     ASSERT(!mImage->getActualFormat().hasDepthOrStencilBits());
108     ASSERT(framebufferLayerCount <= mLayerCount);
109 
110     contextVk->onColorDraw(mLevelIndexGL, mLayerIndex, framebufferLayerCount, mImage, mResolveImage,
111                            mImageSiblingSerial, packedAttachmentIndex);
112 
113     // Multisampled render to texture framebuffers cannot be layered.
114     ASSERT(mResolveImage == nullptr || framebufferLayerCount == 1);
115 }
116 
onColorResolve(ContextVk * contextVk,uint32_t framebufferLayerCount)117 void RenderTargetVk::onColorResolve(ContextVk *contextVk, uint32_t framebufferLayerCount)
118 {
119     ASSERT(!mImage->getActualFormat().hasDepthOrStencilBits());
120     ASSERT(framebufferLayerCount <= mLayerCount);
121     ASSERT(mResolveImage == nullptr);
122 
123     contextVk->onImageRenderPassWrite(mLevelIndexGL, mLayerIndex, framebufferLayerCount,
124                                       VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorWrite,
125                                       mImage);
126 }
127 
onDepthStencilDraw(ContextVk * contextVk,uint32_t framebufferLayerCount)128 void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk, uint32_t framebufferLayerCount)
129 {
130     const angle::Format &format = mImage->getActualFormat();
131     ASSERT(format.hasDepthOrStencilBits());
132     ASSERT(framebufferLayerCount <= mLayerCount);
133 
134     contextVk->onDepthStencilDraw(mLevelIndexGL, mLayerIndex, framebufferLayerCount, mImage,
135                                   mResolveImage, mImageSiblingSerial);
136 }
137 
onDepthStencilResolve(ContextVk * contextVk,uint32_t framebufferLayerCount)138 void RenderTargetVk::onDepthStencilResolve(ContextVk *contextVk, uint32_t framebufferLayerCount)
139 {
140     ASSERT(mImage->getActualFormat().hasDepthOrStencilBits());
141     ASSERT(framebufferLayerCount <= mLayerCount);
142     ASSERT(mResolveImage == nullptr);
143 
144     contextVk->onImageRenderPassWrite(mLevelIndexGL, mLayerIndex, framebufferLayerCount,
145                                       mImage->getAspectFlags(),
146                                       vk::ImageLayout::DepthStencilResolve, mImage);
147 }
148 
getImageForRenderPass()149 vk::ImageHelper &RenderTargetVk::getImageForRenderPass()
150 {
151     ASSERT(mImage && mImage->valid());
152     return *mImage;
153 }
154 
getImageForRenderPass() const155 const vk::ImageHelper &RenderTargetVk::getImageForRenderPass() const
156 {
157     ASSERT(mImage && mImage->valid());
158     return *mImage;
159 }
160 
getResolveImageForRenderPass()161 vk::ImageHelper &RenderTargetVk::getResolveImageForRenderPass()
162 {
163     ASSERT(mResolveImage && mResolveImage->valid());
164     return *mResolveImage;
165 }
166 
getResolveImageForRenderPass() const167 const vk::ImageHelper &RenderTargetVk::getResolveImageForRenderPass() const
168 {
169     ASSERT(mResolveImage && mResolveImage->valid());
170     return *mResolveImage;
171 }
172 
getImageViewImpl(vk::Context * context,const vk::ImageHelper & image,gl::SrgbWriteControlMode mode,vk::ImageViewHelper * imageViews,const vk::ImageView ** imageViewOut) const173 angle::Result RenderTargetVk::getImageViewImpl(vk::Context *context,
174                                                const vk::ImageHelper &image,
175                                                gl::SrgbWriteControlMode mode,
176                                                vk::ImageViewHelper *imageViews,
177                                                const vk::ImageView **imageViewOut) const
178 {
179     ASSERT(image.valid() && imageViews);
180     vk::LevelIndex levelVk = image.toVkLevel(getLevelIndexForImage(image));
181     if (mLayerCount == 1)
182     {
183         return imageViews->getLevelLayerDrawImageView(context, image, levelVk, mLayerIndex, mode,
184                                                       imageViewOut);
185     }
186 
187     // Layered render targets view the whole level or a handful of layers in case of multiview.
188     return imageViews->getLevelDrawImageView(context, image, levelVk, mLayerIndex, mLayerCount,
189                                              mode, imageViewOut);
190 }
191 
getImageView(vk::Context * context,const vk::ImageView ** imageViewOut) const192 angle::Result RenderTargetVk::getImageView(vk::Context *context,
193                                            const vk::ImageView **imageViewOut) const
194 {
195     ASSERT(mImage);
196     return getImageViewImpl(context, *mImage, gl::SrgbWriteControlMode::Default, mImageViews,
197                             imageViewOut);
198 }
199 
getImageViewWithColorspace(vk::Context * context,gl::SrgbWriteControlMode mode,const vk::ImageView ** imageViewOut) const200 angle::Result RenderTargetVk::getImageViewWithColorspace(vk::Context *context,
201                                                          gl::SrgbWriteControlMode mode,
202                                                          const vk::ImageView **imageViewOut) const
203 {
204     ASSERT(mImage);
205     return getImageViewImpl(context, *mImage, mode, mImageViews, imageViewOut);
206 }
207 
getResolveImageView(vk::Context * context,const vk::ImageView ** imageViewOut) const208 angle::Result RenderTargetVk::getResolveImageView(vk::Context *context,
209                                                   const vk::ImageView **imageViewOut) const
210 {
211     ASSERT(mResolveImage);
212     return getImageViewImpl(context, *mResolveImage, gl::SrgbWriteControlMode::Default,
213                             mResolveImageViews, imageViewOut);
214 }
215 
isResolveImageOwnerOfData() const216 bool RenderTargetVk::isResolveImageOwnerOfData() const
217 {
218     // If there's a resolve attachment and the image itself is transient, it's the resolve
219     // attachment that owns the data, so all non-render-pass accesses to the render target data
220     // should go through the resolve attachment.
221     return isImageTransient();
222 }
223 
getOwnerOfData() const224 vk::ImageHelper *RenderTargetVk::getOwnerOfData() const
225 {
226     return isResolveImageOwnerOfData() ? mResolveImage : mImage;
227 }
228 
getCopyImageView(vk::Context * context,const vk::ImageView ** imageViewOut) const229 angle::Result RenderTargetVk::getCopyImageView(vk::Context *context,
230                                                const vk::ImageView **imageViewOut) const
231 {
232     const vk::ImageViewHelper *imageViews =
233         isResolveImageOwnerOfData() ? mResolveImageViews : mImageViews;
234 
235     // If the source of render target is a texture or renderbuffer, this will always be valid.  This
236     // is also where 3D or 2DArray images could be the source of the render target.
237     if (imageViews->hasCopyImageView())
238     {
239         *imageViewOut = &imageViews->getCopyImageView();
240         return angle::Result::Continue;
241     }
242 
243     // Otherwise, this must come from the surface, in which case the image is 2D, so the image view
244     // used to draw is just as good for fetching.  If resolve attachment is present, fetching is
245     // done from that.
246     return isResolveImageOwnerOfData() ? getResolveImageView(context, imageViewOut)
247                                        : getImageView(context, imageViewOut);
248 }
249 
getImageActualFormatID() const250 angle::FormatID RenderTargetVk::getImageActualFormatID() const
251 {
252     ASSERT(mImage && mImage->valid());
253     return mImage->getActualFormatID();
254 }
255 
getImageIntendedFormatID() const256 angle::FormatID RenderTargetVk::getImageIntendedFormatID() const
257 {
258     ASSERT(mImage && mImage->valid());
259     return mImage->getIntendedFormatID();
260 }
261 
getImageActualFormat() const262 const angle::Format &RenderTargetVk::getImageActualFormat() const
263 {
264     ASSERT(mImage && mImage->valid());
265     return mImage->getActualFormat();
266 }
267 
getImageIntendedFormat() const268 const angle::Format &RenderTargetVk::getImageIntendedFormat() const
269 {
270     ASSERT(mImage && mImage->valid());
271     return mImage->getIntendedFormat();
272 }
273 
getExtents() const274 gl::Extents RenderTargetVk::getExtents() const
275 {
276     ASSERT(mImage && mImage->valid());
277     vk::LevelIndex levelVk = mImage->toVkLevel(mLevelIndexGL);
278     return mImage->getLevelExtents2D(levelVk);
279 }
280 
getRotatedExtents() const281 gl::Extents RenderTargetVk::getRotatedExtents() const
282 {
283     ASSERT(mImage && mImage->valid());
284     vk::LevelIndex levelVk = mImage->toVkLevel(mLevelIndexGL);
285     return mImage->getRotatedLevelExtents2D(levelVk);
286 }
287 
getLevelIndexForImage(const vk::ImageHelper & image) const288 gl::LevelIndex RenderTargetVk::getLevelIndexForImage(const vk::ImageHelper &image) const
289 {
290     return (getOwnerOfData()->getImageSerial() == image.getImageSerial()) ? mLevelIndexGL
291                                                                           : gl::LevelIndex(0);
292 }
293 
updateSwapchainImage(vk::ImageHelper * image,vk::ImageViewHelper * imageViews,vk::ImageHelper * resolveImage,vk::ImageViewHelper * resolveImageViews)294 void RenderTargetVk::updateSwapchainImage(vk::ImageHelper *image,
295                                           vk::ImageViewHelper *imageViews,
296                                           vk::ImageHelper *resolveImage,
297                                           vk::ImageViewHelper *resolveImageViews)
298 {
299     ASSERT(image && image->valid() && imageViews);
300     mImage             = image;
301     mImageViews        = imageViews;
302     mResolveImage      = resolveImage;
303     mResolveImageViews = resolveImageViews;
304 }
305 
getImageForCopy() const306 vk::ImageHelper &RenderTargetVk::getImageForCopy() const
307 {
308     ASSERT(mImage && mImage->valid() && (mResolveImage == nullptr || mResolveImage->valid()));
309     return *getOwnerOfData();
310 }
311 
getImageForWrite() const312 vk::ImageHelper &RenderTargetVk::getImageForWrite() const
313 {
314     ASSERT(mImage && mImage->valid() && (mResolveImage == nullptr || mResolveImage->valid()));
315     return *getOwnerOfData();
316 }
317 
flushStagedUpdates(ContextVk * contextVk,vk::ClearValuesArray * deferredClears,uint32_t deferredClearIndex,uint32_t framebufferLayerCount)318 angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk,
319                                                  vk::ClearValuesArray *deferredClears,
320                                                  uint32_t deferredClearIndex,
321                                                  uint32_t framebufferLayerCount)
322 {
323     ASSERT(mImage->valid() && (!isResolveImageOwnerOfData() || mResolveImage->valid()));
324     ASSERT(framebufferLayerCount != 0);
325 
326     // It's impossible to defer clears to slices of a 3D images, as the clear applies to all the
327     // slices, while deferred clears only clear a single slice (where the framebuffer is attached).
328     // Additionally, the layer index for 3D textures is always zero according to Vulkan.
329     uint32_t layerIndex = mLayerIndex;
330     if (mImage->getType() == VK_IMAGE_TYPE_3D)
331     {
332         layerIndex         = 0;
333         deferredClears     = nullptr;
334         deferredClearIndex = 0;
335     }
336 
337     vk::ImageHelper *image = getOwnerOfData();
338 
339     // All updates should be staged on the image that owns the data as the source of truth.  With
340     // multisampled-render-to-texture framebuffers, that is the resolve image.  In that case, even
341     // though deferred clears set the loadOp of the transient multisampled image, the clears
342     // themselves are staged on the resolve image.  The |flushSingleSubresourceStagedUpdates| call
343     // below will either flush all staged updates to the resolve image, or if the only staged update
344     // is a clear, it will accumulate it in the |deferredClears| array.  Later, when the render pass
345     // is started, the deferred clears are applied to the transient multisampled image.
346     ASSERT(!isResolveImageOwnerOfData() ||
347            !mImage->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, mLayerCount));
348     ASSERT(isResolveImageOwnerOfData() || mResolveImage == nullptr ||
349            !mResolveImage->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, mLayerCount));
350 
351     if (!image->hasStagedUpdatesForSubresource(mLevelIndexGL, layerIndex, framebufferLayerCount))
352     {
353         return angle::Result::Continue;
354     }
355 
356     return image->flushSingleSubresourceStagedUpdates(contextVk, mLevelIndexGL, layerIndex,
357                                                       framebufferLayerCount, deferredClears,
358                                                       deferredClearIndex);
359 }
360 
hasDefinedContent() const361 bool RenderTargetVk::hasDefinedContent() const
362 {
363     vk::ImageHelper *image = getOwnerOfData();
364     return image->hasSubresourceDefinedContent(mLevelIndexGL, mLayerIndex, mLayerCount);
365 }
366 
hasDefinedStencilContent() const367 bool RenderTargetVk::hasDefinedStencilContent() const
368 {
369     vk::ImageHelper *image = getOwnerOfData();
370     return image->hasSubresourceDefinedStencilContent(mLevelIndexGL, mLayerIndex, mLayerCount);
371 }
372 
invalidateEntireContent(ContextVk * contextVk,bool * preferToKeepContentsDefinedOut)373 void RenderTargetVk::invalidateEntireContent(ContextVk *contextVk,
374                                              bool *preferToKeepContentsDefinedOut)
375 {
376     vk::ImageHelper *image = getOwnerOfData();
377     image->invalidateSubresourceContent(contextVk, mLevelIndexGL, mLayerIndex, mLayerCount,
378                                         preferToKeepContentsDefinedOut);
379 }
380 
invalidateEntireStencilContent(ContextVk * contextVk,bool * preferToKeepContentsDefinedOut)381 void RenderTargetVk::invalidateEntireStencilContent(ContextVk *contextVk,
382                                                     bool *preferToKeepContentsDefinedOut)
383 {
384     vk::ImageHelper *image = getOwnerOfData();
385     image->invalidateSubresourceStencilContent(contextVk, mLevelIndexGL, mLayerIndex, mLayerCount,
386                                                preferToKeepContentsDefinedOut);
387 }
388 
getImageIndexForClear(uint32_t layerCount) const389 gl::ImageIndex RenderTargetVk::getImageIndexForClear(uint32_t layerCount) const
390 {
391     // Determine the GL type from the Vk Image properties.
392     if (mImage->getType() == VK_IMAGE_TYPE_3D || mImage->getLayerCount() > 1)
393     {
394         // This is used for the sake of staging clears.  The depth slices of the 3D image are
395         // threated as layers for this purpose.
396         //
397         // We also don't need to distinguish 2D array and cube.
398         return gl::ImageIndex::Make2DArrayRange(mLevelIndexGL.get(), mLayerIndex, layerCount);
399     }
400 
401     ASSERT(mLayerIndex == 0);
402     ASSERT(mLayerCount == 1);
403     ASSERT(layerCount == 1);
404     return gl::ImageIndex::Make2D(mLevelIndexGL.get());
405 }
406 }  // namespace rx
407