• 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 // FramebufferVk.cpp:
7 //    Implements the class methods for FramebufferVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
11 
12 #include <array>
13 
14 #include "common/debug.h"
15 #include "common/vulkan/vk_headers.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/Display.h"
18 #include "libANGLE/ErrorStrings.h"
19 #include "libANGLE/formatutils.h"
20 #include "libANGLE/renderer/renderer_utils.h"
21 #include "libANGLE/renderer/vulkan/ContextVk.h"
22 #include "libANGLE/renderer/vulkan/DisplayVk.h"
23 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
24 #include "libANGLE/renderer/vulkan/RendererVk.h"
25 #include "libANGLE/renderer/vulkan/ResourceVk.h"
26 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
27 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
28 
29 namespace rx
30 {
31 
32 namespace
33 {
34 // Clear values are only used when loadOp=Clear is set in clearWithRenderPassOp.  When starting a
35 // new render pass, the clear value is set to an unlikely value (bright pink) to stand out better
36 // in case of a bug.
37 constexpr VkClearValue kUninitializedClearValue = {{{0.95, 0.05, 0.95, 0.95}}};
38 
39 // The value to assign an alpha channel that's emulated.  The type is unsigned int, though it will
40 // automatically convert to the actual data type.
41 constexpr unsigned int kEmulatedAlphaValue = 1;
42 
HasSrcBlitFeature(RendererVk * renderer,RenderTargetVk * srcRenderTarget)43 bool HasSrcBlitFeature(RendererVk *renderer, RenderTargetVk *srcRenderTarget)
44 {
45     angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID();
46     return renderer->hasImageFormatFeatureBits(srcFormatID, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
47 }
48 
HasDstBlitFeature(RendererVk * renderer,RenderTargetVk * dstRenderTarget)49 bool HasDstBlitFeature(RendererVk *renderer, RenderTargetVk *dstRenderTarget)
50 {
51     angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID();
52     return renderer->hasImageFormatFeatureBits(dstFormatID, VK_FORMAT_FEATURE_BLIT_DST_BIT);
53 }
54 
55 // Returns false if destination has any channel the source doesn't.  This means that channel was
56 // emulated and using the Vulkan blit command would overwrite that emulated channel.
AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)57 bool AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
58                                              RenderTargetVk *dstRenderTarget)
59 {
60     const angle::Format &srcFormat = srcRenderTarget->getImageIntendedFormat();
61     const angle::Format &dstFormat = dstRenderTarget->getImageIntendedFormat();
62 
63     // Luminance/alpha formats are not renderable, so they can't have ended up in a framebuffer to
64     // participate in a blit.
65     ASSERT(!dstFormat.isLUMA() && !srcFormat.isLUMA());
66 
67     // All color formats have the red channel.
68     ASSERT(dstFormat.redBits > 0 && srcFormat.redBits > 0);
69 
70     return (dstFormat.greenBits > 0 || srcFormat.greenBits == 0) &&
71            (dstFormat.blueBits > 0 || srcFormat.blueBits == 0) &&
72            (dstFormat.alphaBits > 0 || srcFormat.alphaBits == 0);
73 }
74 
75 // Returns false if formats are not identical.  vkCmdResolveImage and resolve attachments both
76 // require identical formats between source and destination.  vkCmdBlitImage additionally requires
77 // the same for depth/stencil formats.
AreSrcAndDstFormatsIdentical(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)78 bool AreSrcAndDstFormatsIdentical(RenderTargetVk *srcRenderTarget, RenderTargetVk *dstRenderTarget)
79 {
80     angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID();
81     angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID();
82 
83     return srcFormatID == dstFormatID;
84 }
85 
AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)86 bool AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
87                                                     RenderTargetVk *dstRenderTarget)
88 {
89     const angle::Format &srcFormat = srcRenderTarget->getImageIntendedFormat();
90     const angle::Format &dstFormat = dstRenderTarget->getImageIntendedFormat();
91 
92     return (dstFormat.depthBits > 0 || srcFormat.depthBits == 0) &&
93            (dstFormat.stencilBits > 0 || srcFormat.stencilBits == 0);
94 }
95 
EarlyAdjustFlipYForPreRotation(SurfaceRotation blitAngleIn,SurfaceRotation * blitAngleOut,bool * blitFlipYOut)96 void EarlyAdjustFlipYForPreRotation(SurfaceRotation blitAngleIn,
97                                     SurfaceRotation *blitAngleOut,
98                                     bool *blitFlipYOut)
99 {
100     switch (blitAngleIn)
101     {
102         case SurfaceRotation::Identity:
103             // No adjustments needed
104             break;
105         case SurfaceRotation::Rotated90Degrees:
106             *blitAngleOut = SurfaceRotation::Rotated90Degrees;
107             *blitFlipYOut = false;
108             break;
109         case SurfaceRotation::Rotated180Degrees:
110             *blitAngleOut = SurfaceRotation::Rotated180Degrees;
111             break;
112         case SurfaceRotation::Rotated270Degrees:
113             *blitAngleOut = SurfaceRotation::Rotated270Degrees;
114             *blitFlipYOut = false;
115             break;
116         default:
117             UNREACHABLE();
118             break;
119     }
120 }
121 
AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle,const gl::Rectangle & blitAreaIn,const gl::Rectangle & framebufferDimensions,gl::Rectangle * blitAreaOut)122 void AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle,
123                                   const gl::Rectangle &blitAreaIn,
124                                   const gl::Rectangle &framebufferDimensions,
125                                   gl::Rectangle *blitAreaOut)
126 {
127     switch (framebufferAngle)
128     {
129         case SurfaceRotation::Identity:
130             // No adjustments needed
131             break;
132         case SurfaceRotation::Rotated90Degrees:
133             blitAreaOut->x = blitAreaIn.y;
134             blitAreaOut->y = blitAreaIn.x;
135             std::swap(blitAreaOut->width, blitAreaOut->height);
136             break;
137         case SurfaceRotation::Rotated180Degrees:
138             blitAreaOut->x = framebufferDimensions.width - blitAreaIn.x - blitAreaIn.width;
139             blitAreaOut->y = framebufferDimensions.height - blitAreaIn.y - blitAreaIn.height;
140             break;
141         case SurfaceRotation::Rotated270Degrees:
142             blitAreaOut->x = framebufferDimensions.height - blitAreaIn.y - blitAreaIn.height;
143             blitAreaOut->y = framebufferDimensions.width - blitAreaIn.x - blitAreaIn.width;
144             std::swap(blitAreaOut->width, blitAreaOut->height);
145             break;
146         default:
147             UNREACHABLE();
148             break;
149     }
150 }
151 
AdjustDimensionsAndFlipForPreRotation(SurfaceRotation framebufferAngle,gl::Rectangle * framebufferDimensions,bool * flipX,bool * flipY)152 void AdjustDimensionsAndFlipForPreRotation(SurfaceRotation framebufferAngle,
153                                            gl::Rectangle *framebufferDimensions,
154                                            bool *flipX,
155                                            bool *flipY)
156 {
157     switch (framebufferAngle)
158     {
159         case SurfaceRotation::Identity:
160             // No adjustments needed
161             break;
162         case SurfaceRotation::Rotated90Degrees:
163             std::swap(framebufferDimensions->width, framebufferDimensions->height);
164             std::swap(*flipX, *flipY);
165             break;
166         case SurfaceRotation::Rotated180Degrees:
167             break;
168         case SurfaceRotation::Rotated270Degrees:
169             std::swap(framebufferDimensions->width, framebufferDimensions->height);
170             std::swap(*flipX, *flipY);
171             break;
172         default:
173             UNREACHABLE();
174             break;
175     }
176 }
177 
178 // When blitting, the source and destination areas are viewed like UVs.  For example, a 64x64
179 // texture if flipped should have an offset of 64 in either X or Y which corresponds to U or V of 1.
180 // On the other hand, when resolving, the source and destination areas are used as fragment
181 // coordinates to fetch from.  In that case, when flipped, the texture in the above example must
182 // have an offset of 63.
AdjustBlitResolveParametersForResolve(const gl::Rectangle & sourceArea,const gl::Rectangle & destArea,UtilsVk::BlitResolveParameters * params)183 void AdjustBlitResolveParametersForResolve(const gl::Rectangle &sourceArea,
184                                            const gl::Rectangle &destArea,
185                                            UtilsVk::BlitResolveParameters *params)
186 {
187     params->srcOffset[0] = sourceArea.x;
188     params->srcOffset[1] = sourceArea.y;
189     params->dstOffset[0] = destArea.x;
190     params->dstOffset[1] = destArea.y;
191 
192     if (sourceArea.isReversedX())
193     {
194         ASSERT(sourceArea.x > 0);
195         --params->srcOffset[0];
196     }
197     if (sourceArea.isReversedY())
198     {
199         ASSERT(sourceArea.y > 0);
200         --params->srcOffset[1];
201     }
202     if (destArea.isReversedX())
203     {
204         ASSERT(destArea.x > 0);
205         --params->dstOffset[0];
206     }
207     if (destArea.isReversedY())
208     {
209         ASSERT(destArea.y > 0);
210         --params->dstOffset[1];
211     }
212 }
213 
214 // Potentially make adjustments for pre-rotatation.  Depending on the angle some of the params need
215 // to be swapped and/or changes made to which axis are flipped.
AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,SurfaceRotation srcFramebufferAngle,UtilsVk::BlitResolveParameters * params)216 void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,
217                                                SurfaceRotation srcFramebufferAngle,
218                                                UtilsVk::BlitResolveParameters *params)
219 {
220     switch (framebufferAngle)
221     {
222         case SurfaceRotation::Identity:
223             break;
224         case SurfaceRotation::Rotated90Degrees:
225             std::swap(params->stretch[0], params->stretch[1]);
226             std::swap(params->srcOffset[0], params->srcOffset[1]);
227             std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
228             std::swap(params->flipX, params->flipY);
229             if (srcFramebufferAngle == framebufferAngle)
230             {
231                 std::swap(params->dstOffset[0], params->dstOffset[1]);
232                 std::swap(params->stretch[0], params->stretch[1]);
233             }
234             break;
235         case SurfaceRotation::Rotated180Degrees:
236             // Combine flip info with api flip.
237             params->flipX = !params->flipX;
238             params->flipY = !params->flipY;
239             break;
240         case SurfaceRotation::Rotated270Degrees:
241             std::swap(params->stretch[0], params->stretch[1]);
242             std::swap(params->srcOffset[0], params->srcOffset[1]);
243             std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
244             if (srcFramebufferAngle == framebufferAngle)
245             {
246                 std::swap(params->stretch[0], params->stretch[1]);
247             }
248             // Combine flip info with api flip.
249             params->flipX = !params->flipX;
250             params->flipY = !params->flipY;
251             std::swap(params->flipX, params->flipY);
252 
253             break;
254         default:
255             UNREACHABLE();
256             break;
257     }
258 }
259 
HasResolveAttachment(const gl::AttachmentArray<RenderTargetVk * > & colorRenderTargets,const gl::DrawBufferMask & getEnabledDrawBuffers)260 bool HasResolveAttachment(const gl::AttachmentArray<RenderTargetVk *> &colorRenderTargets,
261                           const gl::DrawBufferMask &getEnabledDrawBuffers)
262 {
263     for (size_t colorIndexGL : getEnabledDrawBuffers)
264     {
265         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
266         if (colorRenderTarget->hasResolveAttachment())
267         {
268             return true;
269         }
270     }
271     return false;
272 }
273 
MakeUnresolveAttachmentMask(const vk::RenderPassDesc & desc)274 vk::FramebufferNonResolveAttachmentMask MakeUnresolveAttachmentMask(const vk::RenderPassDesc &desc)
275 {
276     vk::FramebufferNonResolveAttachmentMask unresolveMask(
277         desc.getColorUnresolveAttachmentMask().bits());
278     if (desc.hasDepthUnresolveAttachment() || desc.hasStencilUnresolveAttachment())
279     {
280         // This mask only needs to know if the depth/stencil attachment needs to be unresolved, and
281         // is agnostic of the aspect.
282         unresolveMask.set(vk::kUnpackedDepthIndex);
283     }
284     return unresolveMask;
285 }
286 
IsAnyAttachment3DWithoutAllLayers(const RenderTargetCache<RenderTargetVk> & renderTargetCache,gl::DrawBufferMask colorAttachmentsMask,uint32_t framebufferLayerCount)287 bool IsAnyAttachment3DWithoutAllLayers(const RenderTargetCache<RenderTargetVk> &renderTargetCache,
288                                        gl::DrawBufferMask colorAttachmentsMask,
289                                        uint32_t framebufferLayerCount)
290 {
291     const auto &colorRenderTargets = renderTargetCache.getColors();
292     for (size_t colorIndexGL : colorAttachmentsMask)
293     {
294         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
295         ASSERT(colorRenderTarget);
296 
297         const vk::ImageHelper &image = colorRenderTarget->getImageForRenderPass();
298 
299         if (image.getType() == VK_IMAGE_TYPE_3D && image.getExtents().depth > framebufferLayerCount)
300         {
301             return true;
302         }
303     }
304 
305     // Depth/stencil attachments cannot be 3D.
306     ASSERT(renderTargetCache.getDepthStencil() == nullptr ||
307            renderTargetCache.getDepthStencil()->getImageForRenderPass().getType() !=
308                VK_IMAGE_TYPE_3D);
309 
310     return false;
311 }
312 }  // anonymous namespace
313 
FramebufferVk(RendererVk * renderer,const gl::FramebufferState & state)314 FramebufferVk::FramebufferVk(RendererVk *renderer, const gl::FramebufferState &state)
315     : FramebufferImpl(state), mBackbuffer(nullptr), mActiveColorComponentMasksForClear(0)
316 {
317     if (mState.isDefault())
318     {
319         // These are immutable for system default framebuffer.
320         mCurrentFramebufferDesc.updateLayerCount(1);
321         mCurrentFramebufferDesc.updateIsMultiview(false);
322     }
323 
324     mIsCurrentFramebufferCached = !renderer->getFeatures().supportsImagelessFramebuffer.enabled;
325 }
326 
327 FramebufferVk::~FramebufferVk() = default;
328 
destroy(const gl::Context * context)329 void FramebufferVk::destroy(const gl::Context *context)
330 {
331     ContextVk *contextVk = vk::GetImpl(context);
332     releaseCurrentFramebuffer(contextVk);
333 }
334 
insertCache(ContextVk * contextVk,const vk::FramebufferDesc & desc,vk::FramebufferHelper && newFramebuffer)335 void FramebufferVk::insertCache(ContextVk *contextVk,
336                                 const vk::FramebufferDesc &desc,
337                                 vk::FramebufferHelper &&newFramebuffer)
338 {
339     // Add it into per share group cache
340     contextVk->getShareGroup()->getFramebufferCache().insert(contextVk, desc,
341                                                              std::move(newFramebuffer));
342 
343     // Create a refcounted cache key object and have each attachment keep a refcount to it so that
344     // it can be destroyed promptly if those attachments change.
345     const vk::SharedFramebufferCacheKey sharedFramebufferCacheKey =
346         vk::CreateSharedFramebufferCacheKey(desc);
347 
348     // Ask each attachment to hold a reference to the cache so that when any attachment is
349     // released, the cache can be destroyed.
350     const auto &colorRenderTargets = mRenderTargetCache.getColors();
351     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
352     {
353         colorRenderTargets[colorIndexGL]->onNewFramebuffer(sharedFramebufferCacheKey);
354     }
355 
356     if (getDepthStencilRenderTarget())
357     {
358         getDepthStencilRenderTarget()->onNewFramebuffer(sharedFramebufferCacheKey);
359     }
360 }
361 
discard(const gl::Context * context,size_t count,const GLenum * attachments)362 angle::Result FramebufferVk::discard(const gl::Context *context,
363                                      size_t count,
364                                      const GLenum *attachments)
365 {
366     return invalidate(context, count, attachments);
367 }
368 
invalidate(const gl::Context * context,size_t count,const GLenum * attachments)369 angle::Result FramebufferVk::invalidate(const gl::Context *context,
370                                         size_t count,
371                                         const GLenum *attachments)
372 {
373     ContextVk *contextVk = vk::GetImpl(context);
374 
375     ANGLE_TRY(invalidateImpl(contextVk, count, attachments, false,
376                              getRotatedCompleteRenderArea(contextVk)));
377     return angle::Result::Continue;
378 }
379 
invalidateSub(const gl::Context * context,size_t count,const GLenum * attachments,const gl::Rectangle & area)380 angle::Result FramebufferVk::invalidateSub(const gl::Context *context,
381                                            size_t count,
382                                            const GLenum *attachments,
383                                            const gl::Rectangle &area)
384 {
385     ContextVk *contextVk = vk::GetImpl(context);
386 
387     const gl::Rectangle nonRotatedCompleteRenderArea = getNonRotatedCompleteRenderArea();
388     gl::Rectangle rotatedInvalidateArea;
389     RotateRectangle(contextVk->getRotationDrawFramebuffer(),
390                     contextVk->isViewportFlipEnabledForDrawFBO(),
391                     nonRotatedCompleteRenderArea.width, nonRotatedCompleteRenderArea.height, area,
392                     &rotatedInvalidateArea);
393 
394     // If invalidateSub() covers the whole framebuffer area, make it behave as invalidate().
395     // The invalidate area is clipped to the render area for use inside invalidateImpl.
396     const gl::Rectangle completeRenderArea = getRotatedCompleteRenderArea(contextVk);
397     if (ClipRectangle(rotatedInvalidateArea, completeRenderArea, &rotatedInvalidateArea) &&
398         rotatedInvalidateArea == completeRenderArea)
399     {
400         return invalidate(context, count, attachments);
401     }
402 
403     // If there are deferred clears, redefer them.  syncState may have accumulated deferred clears,
404     // but if the framebuffer's attachments are used after this call not through the framebuffer,
405     // those clears wouldn't get flushed otherwise (for example as the destination of
406     // glCopyTex[Sub]Image, shader storage image, etc).
407     redeferClears(contextVk);
408 
409     if (contextVk->hasActiveRenderPass() &&
410         rotatedInvalidateArea.encloses(contextVk->getStartedRenderPassCommands().getRenderArea()))
411     {
412         // Because the render pass's render area is within the invalidated area, it is fine for
413         // invalidateImpl() to use a storeOp of DONT_CARE (i.e. fine to not store the contents of
414         // the invalidated area).
415         ANGLE_TRY(invalidateImpl(contextVk, count, attachments, true, rotatedInvalidateArea));
416     }
417     else
418     {
419         ANGLE_VK_PERF_WARNING(
420             contextVk, GL_DEBUG_SEVERITY_LOW,
421             "InvalidateSubFramebuffer ignored due to area not covering the render area");
422     }
423 
424     return angle::Result::Continue;
425 }
426 
clear(const gl::Context * context,GLbitfield mask)427 angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
428 {
429     ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::clear");
430     ContextVk *contextVk = vk::GetImpl(context);
431 
432     bool clearColor   = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT));
433     bool clearDepth   = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT));
434     bool clearStencil = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_STENCIL_BUFFER_BIT));
435     gl::DrawBufferMask clearColorBuffers;
436     if (clearColor)
437     {
438         clearColorBuffers = mState.getEnabledDrawBuffers();
439     }
440 
441     const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
442     const VkClearDepthStencilValue &clearDepthStencilValue =
443         contextVk->getClearDepthStencilValue().depthStencil;
444 
445     return clearImpl(context, clearColorBuffers, clearDepth, clearStencil, clearColorValue,
446                      clearDepthStencilValue);
447 }
448 
clearImpl(const gl::Context * context,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)449 angle::Result FramebufferVk::clearImpl(const gl::Context *context,
450                                        gl::DrawBufferMask clearColorBuffers,
451                                        bool clearDepth,
452                                        bool clearStencil,
453                                        const VkClearColorValue &clearColorValue,
454                                        const VkClearDepthStencilValue &clearDepthStencilValue)
455 {
456     ContextVk *contextVk = vk::GetImpl(context);
457 
458     const gl::Rectangle scissoredRenderArea = getRotatedScissoredRenderArea(contextVk);
459     ASSERT(scissoredRenderArea.width != 0 && scissoredRenderArea.height != 0);
460 
461     // This function assumes that only enabled attachments are asked to be cleared.
462     ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
463     ASSERT(!clearDepth || mState.getDepthAttachment() != nullptr);
464     ASSERT(!clearStencil || mState.getStencilAttachment() != nullptr);
465 
466     gl::BlendStateExt::ColorMaskStorage::Type colorMasks = contextVk->getClearColorMasks();
467     bool clearColor                                      = clearColorBuffers.any();
468 
469     // When this function is called, there should always be something to clear.
470     ASSERT(clearColor || clearDepth || clearStencil);
471 
472     const uint8_t stencilMask =
473         static_cast<uint8_t>(contextVk->getState().getDepthStencilState().stencilWritemask);
474 
475     // The front-end should ensure we don't attempt to clear color if all channels are masked.
476     ASSERT(!clearColor || colorMasks != 0);
477     // The front-end should ensure we don't attempt to clear depth if depth write is disabled.
478     ASSERT(!clearDepth || contextVk->getState().getDepthStencilState().depthMask);
479     // The front-end should ensure we don't attempt to clear stencil if all bits are masked.
480     ASSERT(!clearStencil || stencilMask != 0);
481 
482     // Make sure to close the render pass now if in read-only depth/stencil feedback loop mode and
483     // depth/stencil is being cleared.
484     if (clearDepth || clearStencil)
485     {
486         ANGLE_TRY(contextVk->updateRenderPassDepthFeedbackLoopMode(
487             clearDepth ? UpdateDepthFeedbackLoopReason::Clear : UpdateDepthFeedbackLoopReason::None,
488             clearStencil ? UpdateDepthFeedbackLoopReason::Clear
489                          : UpdateDepthFeedbackLoopReason::None));
490     }
491 
492     const bool scissoredClear = scissoredRenderArea != getRotatedCompleteRenderArea(contextVk);
493 
494     // We use the draw path if scissored clear, or color or stencil are masked.  Note that depth
495     // clearing is already disabled if there's a depth mask.
496     const bool maskedClearColor = clearColor && (mActiveColorComponentMasksForClear & colorMasks) !=
497                                                     mActiveColorComponentMasksForClear;
498     const bool maskedClearStencil = clearStencil && stencilMask != 0xFF;
499 
500     bool clearColorWithDraw   = clearColor && (maskedClearColor || scissoredClear);
501     bool clearDepthWithDraw   = clearDepth && scissoredClear;
502     bool clearStencilWithDraw = clearStencil && (maskedClearStencil || scissoredClear);
503 
504     const bool isMidRenderPassClear =
505         contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial) &&
506         !contextVk->getStartedRenderPassCommands().getCommandBuffer().empty();
507     if (isMidRenderPassClear)
508     {
509         // Emit debug-util markers for this mid-render-pass clear
510         ANGLE_TRY(
511             contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
512     }
513     else
514     {
515         ASSERT(!contextVk->hasActiveRenderPass() ||
516                contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial));
517         // Emit debug-util markers for this outside-render-pass clear
518         ANGLE_TRY(
519             contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd));
520     }
521 
522     const bool preferDrawOverClearAttachments =
523         contextVk->getRenderer()->getFeatures().preferDrawClearOverVkCmdClearAttachments.enabled;
524 
525     // Merge current clears with the deferred clears, then proceed with only processing deferred
526     // clears.  This simplifies the clear paths such that they don't need to consider both the
527     // current and deferred clears.  Additionally, it avoids needing to undo an unresolve
528     // operation; say attachment A is deferred cleared and multisampled-render-to-texture
529     // attachment B is currently cleared.  Assuming a render pass needs to start (because for
530     // example attachment C needs to clear with a draw path), starting one with only deferred
531     // clears and then applying the current clears won't work as attachment B is unresolved, and
532     // there are no facilities to undo that.
533     if (preferDrawOverClearAttachments && isMidRenderPassClear)
534     {
535         // On buggy hardware, prefer to clear with a draw call instead of vkCmdClearAttachments.
536         // Note that it's impossible to have deferred clears in the middle of the render pass.
537         ASSERT(!mDeferredClears.any());
538 
539         clearColorWithDraw   = clearColor;
540         clearDepthWithDraw   = clearDepth;
541         clearStencilWithDraw = clearStencil;
542     }
543     else
544     {
545         gl::DrawBufferMask clearColorDrawBuffersMask;
546         if (clearColor && !clearColorWithDraw)
547         {
548             clearColorDrawBuffersMask = clearColorBuffers;
549         }
550 
551         mergeClearsWithDeferredClears(clearColorDrawBuffersMask, clearDepth && !clearDepthWithDraw,
552                                       clearStencil && !clearStencilWithDraw, clearColorValue,
553                                       clearDepthStencilValue);
554     }
555 
556     // If any deferred clears, we can further defer them, clear them with vkCmdClearAttachments or
557     // flush them if necessary.
558     if (mDeferredClears.any())
559     {
560         const bool clearAnyWithDraw =
561             clearColorWithDraw || clearDepthWithDraw || clearStencilWithDraw;
562 
563         bool isAnyAttachment3DWithoutAllLayers =
564             IsAnyAttachment3DWithoutAllLayers(mRenderTargetCache, mState.getColorAttachmentsMask(),
565                                               mCurrentFramebufferDesc.getLayerCount());
566 
567         // If we are in an active renderpass that has recorded commands and the framebuffer hasn't
568         // changed, inline the clear.
569         if (isMidRenderPassClear)
570         {
571             ANGLE_VK_PERF_WARNING(
572                 contextVk, GL_DEBUG_SEVERITY_LOW,
573                 "Clear effectively discarding previous draw call results. Suggest earlier Clear "
574                 "followed by masked color or depth/stencil draw calls instead, or "
575                 "glInvalidateFramebuffer to discard data instead");
576 
577             ASSERT(!preferDrawOverClearAttachments);
578 
579             // clearWithCommand will operate on deferred clears.
580             clearWithCommand(contextVk, scissoredRenderArea, ClearWithCommand::OptimizeWithLoadOp,
581                              &mDeferredClears);
582 
583             // clearWithCommand will clear only those attachments that have been used in the render
584             // pass, and removes them from mDeferredClears.  Any deferred clears that are left can
585             // be performed with a renderpass loadOp.
586             if (mDeferredClears.any())
587             {
588                 clearWithLoadOp(contextVk);
589             }
590         }
591         else
592         {
593             if (contextVk->hasActiveRenderPass())
594             {
595                 // Typically, clears are deferred such that it's impossible to have a render pass
596                 // opened without any additional commands recorded on it.  This is not true for some
597                 // corner cases, such as with 3D or external attachments.  In those cases, a clear
598                 // can open a render pass that's otherwise empty, and additional clears can continue
599                 // to be accumulated in the render pass loadOps.
600                 ASSERT(isAnyAttachment3DWithoutAllLayers || hasAnyExternalAttachments());
601                 clearWithLoadOp(contextVk);
602             }
603 
604             // This path will defer the current clears along with deferred clears.  This won't work
605             // if any attachment needs to be subsequently cleared with a draw call.  In that case,
606             // flush deferred clears, which will start a render pass with deferred clear values.
607             // The subsequent draw call will then operate on the cleared attachments.
608             //
609             // Additionally, if the framebuffer is layered, any attachment is 3D and it has a larger
610             // depth than the framebuffer layers, clears cannot be deferred.  This is because the
611             // clear may later need to be flushed with vkCmdClearColorImage, which cannot partially
612             // clear the 3D texture.  In that case, the clears are flushed immediately too.
613             //
614             // For external images such as from AHBs, the clears are not deferred so that they are
615             // definitely applied before the application uses them outside of the control of ANGLE.
616             if (clearAnyWithDraw || isAnyAttachment3DWithoutAllLayers ||
617                 hasAnyExternalAttachments())
618             {
619                 ANGLE_TRY(flushDeferredClears(contextVk));
620             }
621             else
622             {
623                 redeferClears(contextVk);
624             }
625         }
626 
627         // If nothing left to clear, early out.
628         if (!clearAnyWithDraw)
629         {
630             ASSERT(mDeferredClears.empty());
631             return angle::Result::Continue;
632         }
633     }
634 
635     if (!clearColorWithDraw)
636     {
637         clearColorBuffers.reset();
638     }
639 
640     // If we reach here simply because the clear is scissored (as opposed to masked), use
641     // vkCmdClearAttachments to clear the attachments.  The attachments that are masked will
642     // continue to use a draw call.  For depth, vkCmdClearAttachments can always be used, and no
643     // shader/pipeline support would then be required (though this is pending removal of the
644     // preferDrawOverClearAttachments workaround).
645     //
646     // A potential optimization is to use loadOp=Clear for scissored clears, but care needs to be
647     // taken to either break the render pass on growRenderArea(), or to turn the op back to Load and
648     // revert to vkCmdClearAttachments.  This is not currently deemed necessary.
649     if (((clearColorBuffers.any() && !mEmulatedAlphaAttachmentMask.any() && !maskedClearColor) ||
650          clearDepthWithDraw || (clearStencilWithDraw && !maskedClearStencil)) &&
651         !preferDrawOverClearAttachments)
652     {
653         if (!contextVk->hasActiveRenderPass())
654         {
655             // Start a new render pass if necessary to record the commands.
656             vk::RenderPassCommandBuffer *commandBuffer;
657             gl::Rectangle renderArea = getRenderArea(contextVk);
658             ANGLE_TRY(contextVk->startRenderPass(renderArea, &commandBuffer, nullptr));
659         }
660 
661         // Build clear values
662         vk::ClearValuesArray clears;
663         if (!maskedClearColor && !mEmulatedAlphaAttachmentMask.any())
664         {
665             VkClearValue colorClearValue = {};
666             colorClearValue.color        = clearColorValue;
667             for (size_t colorIndexGL : clearColorBuffers)
668             {
669                 clears.store(static_cast<uint32_t>(colorIndexGL), VK_IMAGE_ASPECT_COLOR_BIT,
670                              colorClearValue);
671             }
672             clearColorBuffers.reset();
673         }
674         VkImageAspectFlags dsAspectFlags = 0;
675         if (clearDepthWithDraw)
676         {
677             dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
678             clearDepthWithDraw = false;
679         }
680         if (clearStencilWithDraw && !maskedClearStencil)
681         {
682             dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
683             clearStencilWithDraw = false;
684         }
685         if (dsAspectFlags != 0)
686         {
687             VkClearValue dsClearValue = {};
688             dsClearValue.depthStencil = clearDepthStencilValue;
689             clears.store(vk::kUnpackedDepthIndex, dsAspectFlags, dsClearValue);
690         }
691 
692         clearWithCommand(contextVk, scissoredRenderArea, ClearWithCommand::Always, &clears);
693 
694         if (!clearColorBuffers.any() && !clearStencilWithDraw)
695         {
696             ASSERT(!clearDepthWithDraw);
697             return angle::Result::Continue;
698         }
699     }
700 
701     // The most costly clear mode is when we need to mask out specific color channels or stencil
702     // bits. This can only be done with a draw call.
703     return clearWithDraw(contextVk, scissoredRenderArea, clearColorBuffers, clearDepthWithDraw,
704                          clearStencilWithDraw, colorMasks, stencilMask, clearColorValue,
705                          clearDepthStencilValue);
706 }
707 
clearBufferfv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLfloat * values)708 angle::Result FramebufferVk::clearBufferfv(const gl::Context *context,
709                                            GLenum buffer,
710                                            GLint drawbuffer,
711                                            const GLfloat *values)
712 {
713     VkClearValue clearValue = {};
714 
715     bool clearDepth = false;
716     gl::DrawBufferMask clearColorBuffers;
717 
718     if (buffer == GL_DEPTH)
719     {
720         clearDepth                    = true;
721         clearValue.depthStencil.depth = values[0];
722     }
723     else
724     {
725         clearColorBuffers.set(drawbuffer);
726         clearValue.color.float32[0] = values[0];
727         clearValue.color.float32[1] = values[1];
728         clearValue.color.float32[2] = values[2];
729         clearValue.color.float32[3] = values[3];
730     }
731 
732     return clearImpl(context, clearColorBuffers, clearDepth, false, clearValue.color,
733                      clearValue.depthStencil);
734 }
735 
clearBufferuiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLuint * values)736 angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context,
737                                             GLenum buffer,
738                                             GLint drawbuffer,
739                                             const GLuint *values)
740 {
741     VkClearValue clearValue = {};
742 
743     gl::DrawBufferMask clearColorBuffers;
744     clearColorBuffers.set(drawbuffer);
745 
746     clearValue.color.uint32[0] = values[0];
747     clearValue.color.uint32[1] = values[1];
748     clearValue.color.uint32[2] = values[2];
749     clearValue.color.uint32[3] = values[3];
750 
751     return clearImpl(context, clearColorBuffers, false, false, clearValue.color,
752                      clearValue.depthStencil);
753 }
754 
clearBufferiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLint * values)755 angle::Result FramebufferVk::clearBufferiv(const gl::Context *context,
756                                            GLenum buffer,
757                                            GLint drawbuffer,
758                                            const GLint *values)
759 {
760     VkClearValue clearValue = {};
761 
762     bool clearStencil = false;
763     gl::DrawBufferMask clearColorBuffers;
764 
765     if (buffer == GL_STENCIL)
766     {
767         clearStencil                    = true;
768         clearValue.depthStencil.stencil = static_cast<uint8_t>(values[0]);
769     }
770     else
771     {
772         clearColorBuffers.set(drawbuffer);
773         clearValue.color.int32[0] = values[0];
774         clearValue.color.int32[1] = values[1];
775         clearValue.color.int32[2] = values[2];
776         clearValue.color.int32[3] = values[3];
777     }
778 
779     return clearImpl(context, clearColorBuffers, false, clearStencil, clearValue.color,
780                      clearValue.depthStencil);
781 }
782 
clearBufferfi(const gl::Context * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)783 angle::Result FramebufferVk::clearBufferfi(const gl::Context *context,
784                                            GLenum buffer,
785                                            GLint drawbuffer,
786                                            GLfloat depth,
787                                            GLint stencil)
788 {
789     VkClearValue clearValue = {};
790 
791     clearValue.depthStencil.depth   = depth;
792     clearValue.depthStencil.stencil = static_cast<uint8_t>(stencil);
793 
794     return clearImpl(context, gl::DrawBufferMask(), true, true, clearValue.color,
795                      clearValue.depthStencil);
796 }
797 
getImplementationColorReadFormat(const gl::Context * context) const798 const gl::InternalFormat &FramebufferVk::getImplementationColorReadFormat(
799     const gl::Context *context) const
800 {
801     ContextVk *contextVk       = vk::GetImpl(context);
802     GLenum sizedFormat         = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
803     const vk::Format &vkFormat = contextVk->getRenderer()->getFormat(sizedFormat);
804     GLenum implFormat = vkFormat.getActualRenderableImageFormat().fboImplementationInternalFormat;
805     return gl::GetSizedInternalFormatInfo(implFormat);
806 }
807 
readPixels(const gl::Context * context,const gl::Rectangle & area,GLenum format,GLenum type,const gl::PixelPackState & pack,gl::Buffer * packBuffer,void * pixels)808 angle::Result FramebufferVk::readPixels(const gl::Context *context,
809                                         const gl::Rectangle &area,
810                                         GLenum format,
811                                         GLenum type,
812                                         const gl::PixelPackState &pack,
813                                         gl::Buffer *packBuffer,
814                                         void *pixels)
815 {
816     // Clip read area to framebuffer.
817     const gl::Extents &fbSize = getState().getReadPixelsAttachment(format)->getSize();
818     const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
819     ContextVk *contextVk = vk::GetImpl(context);
820 
821     gl::Rectangle clippedArea;
822     if (!ClipRectangle(area, fbRect, &clippedArea))
823     {
824         // nothing to read
825         return angle::Result::Continue;
826     }
827 
828     // Flush any deferred clears.
829     ANGLE_TRY(flushDeferredClears(contextVk));
830 
831     GLuint outputSkipBytes = 0;
832     PackPixelsParams params;
833     ANGLE_TRY(vk::ImageHelper::GetReadPixelsParams(contextVk, pack, packBuffer, format, type, area,
834                                                    clippedArea, &params, &outputSkipBytes));
835 
836     bool flipY = contextVk->isViewportFlipEnabledForReadFBO();
837     switch (params.rotation = contextVk->getRotationReadFramebuffer())
838     {
839         case SurfaceRotation::Identity:
840             // Do not rotate gl_Position (surface matches the device's orientation):
841             if (flipY)
842             {
843                 params.area.y = fbRect.height - clippedArea.y - clippedArea.height;
844             }
845             break;
846         case SurfaceRotation::Rotated90Degrees:
847             // Rotate gl_Position 90 degrees:
848             params.area.x = clippedArea.y;
849             params.area.y =
850                 flipY ? clippedArea.x : fbRect.width - clippedArea.x - clippedArea.width;
851             std::swap(params.area.width, params.area.height);
852             break;
853         case SurfaceRotation::Rotated180Degrees:
854             // Rotate gl_Position 180 degrees:
855             params.area.x = fbRect.width - clippedArea.x - clippedArea.width;
856             params.area.y =
857                 flipY ? clippedArea.y : fbRect.height - clippedArea.y - clippedArea.height;
858             break;
859         case SurfaceRotation::Rotated270Degrees:
860             // Rotate gl_Position 270 degrees:
861             params.area.x = fbRect.height - clippedArea.y - clippedArea.height;
862             params.area.y =
863                 flipY ? fbRect.width - clippedArea.x - clippedArea.width : clippedArea.x;
864             std::swap(params.area.width, params.area.height);
865             break;
866         default:
867             UNREACHABLE();
868             break;
869     }
870     if (flipY)
871     {
872         params.reverseRowOrder = !params.reverseRowOrder;
873     }
874 
875     ANGLE_TRY(readPixelsImpl(contextVk, params.area, params, getReadPixelsAspectFlags(format),
876                              getReadPixelsRenderTarget(format),
877                              static_cast<uint8_t *>(pixels) + outputSkipBytes));
878     return angle::Result::Continue;
879 }
880 
getDepthStencilRenderTarget() const881 RenderTargetVk *FramebufferVk::getDepthStencilRenderTarget() const
882 {
883     return mRenderTargetCache.getDepthStencil();
884 }
885 
getColorDrawRenderTarget(size_t colorIndexGL) const886 RenderTargetVk *FramebufferVk::getColorDrawRenderTarget(size_t colorIndexGL) const
887 {
888     RenderTargetVk *renderTarget = mRenderTargetCache.getColorDraw(mState, colorIndexGL);
889     ASSERT(renderTarget && renderTarget->getImageForRenderPass().valid());
890     return renderTarget;
891 }
892 
getColorReadRenderTarget() const893 RenderTargetVk *FramebufferVk::getColorReadRenderTarget() const
894 {
895     RenderTargetVk *renderTarget = mRenderTargetCache.getColorRead(mState);
896     ASSERT(renderTarget && renderTarget->getImageForRenderPass().valid());
897     return renderTarget;
898 }
899 
getReadPixelsRenderTarget(GLenum format) const900 RenderTargetVk *FramebufferVk::getReadPixelsRenderTarget(GLenum format) const
901 {
902     switch (format)
903     {
904         case GL_DEPTH_COMPONENT:
905         case GL_STENCIL_INDEX_OES:
906         case GL_DEPTH_STENCIL_OES:
907             return getDepthStencilRenderTarget();
908         default:
909             return getColorReadRenderTarget();
910     }
911 }
912 
getReadPixelsAspectFlags(GLenum format) const913 VkImageAspectFlagBits FramebufferVk::getReadPixelsAspectFlags(GLenum format) const
914 {
915     switch (format)
916     {
917         case GL_DEPTH_COMPONENT:
918             return VK_IMAGE_ASPECT_DEPTH_BIT;
919         case GL_STENCIL_INDEX_OES:
920             return VK_IMAGE_ASPECT_STENCIL_BIT;
921         case GL_DEPTH_STENCIL_OES:
922             return vk::IMAGE_ASPECT_DEPTH_STENCIL;
923         default:
924             return VK_IMAGE_ASPECT_COLOR_BIT;
925     }
926 }
927 
blitWithCommand(ContextVk * contextVk,const gl::Rectangle & sourceArea,const gl::Rectangle & destArea,RenderTargetVk * readRenderTarget,RenderTargetVk * drawRenderTarget,GLenum filter,bool colorBlit,bool depthBlit,bool stencilBlit,bool flipX,bool flipY)928 angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
929                                              const gl::Rectangle &sourceArea,
930                                              const gl::Rectangle &destArea,
931                                              RenderTargetVk *readRenderTarget,
932                                              RenderTargetVk *drawRenderTarget,
933                                              GLenum filter,
934                                              bool colorBlit,
935                                              bool depthBlit,
936                                              bool stencilBlit,
937                                              bool flipX,
938                                              bool flipY)
939 {
940     // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
941     // it should never be the case that both color and depth/stencil need to be blitted at
942     // at the same time.
943     ASSERT(colorBlit != (depthBlit || stencilBlit));
944 
945     vk::ImageHelper *srcImage = &readRenderTarget->getImageForCopy();
946     vk::ImageHelper *dstImage = &drawRenderTarget->getImageForWrite();
947 
948     VkImageAspectFlags imageAspectMask = srcImage->getAspectFlags();
949     VkImageAspectFlags blitAspectMask  = imageAspectMask;
950 
951     // Remove depth or stencil aspects if they are not requested to be blitted.
952     if (!depthBlit)
953     {
954         blitAspectMask &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
955     }
956     if (!stencilBlit)
957     {
958         blitAspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
959     }
960 
961     vk::CommandBufferAccess access;
962     access.onImageTransferRead(imageAspectMask, srcImage);
963     access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
964                                 drawRenderTarget->getLayerIndex(), 1, imageAspectMask, dstImage);
965     vk::OutsideRenderPassCommandBuffer *commandBuffer;
966     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
967 
968     VkImageBlit blit               = {};
969     blit.srcSubresource.aspectMask = blitAspectMask;
970     blit.srcSubresource.mipLevel   = srcImage->toVkLevel(readRenderTarget->getLevelIndex()).get();
971     blit.srcSubresource.baseArrayLayer = readRenderTarget->getLayerIndex();
972     blit.srcSubresource.layerCount     = 1;
973     blit.srcOffsets[0]                 = {sourceArea.x0(), sourceArea.y0(), 0};
974     blit.srcOffsets[1]                 = {sourceArea.x1(), sourceArea.y1(), 1};
975     blit.dstSubresource.aspectMask     = blitAspectMask;
976     blit.dstSubresource.mipLevel = dstImage->toVkLevel(drawRenderTarget->getLevelIndex()).get();
977     blit.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
978     blit.dstSubresource.layerCount     = 1;
979     blit.dstOffsets[0]                 = {destArea.x0(), destArea.y0(), 0};
980     blit.dstOffsets[1]                 = {destArea.x1(), destArea.y1(), 1};
981 
982     commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
983                              dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
984                              gl_vk::GetFilter(filter));
985 
986     return angle::Result::Continue;
987 }
988 
blit(const gl::Context * context,const gl::Rectangle & sourceAreaIn,const gl::Rectangle & destAreaIn,GLbitfield mask,GLenum filter)989 angle::Result FramebufferVk::blit(const gl::Context *context,
990                                   const gl::Rectangle &sourceAreaIn,
991                                   const gl::Rectangle &destAreaIn,
992                                   GLbitfield mask,
993                                   GLenum filter)
994 {
995     ContextVk *contextVk = vk::GetImpl(context);
996     RendererVk *renderer = contextVk->getRenderer();
997     UtilsVk &utilsVk     = contextVk->getUtils();
998 
999     // If any clears were picked up when syncing the read framebuffer (as the blit source), redefer
1000     // them.  They correspond to attachments that are not used in the blit.  This will cause the
1001     // read framebuffer to become dirty, so the attachments will be synced again on the next command
1002     // that might be using them.
1003     const gl::State &glState              = contextVk->getState();
1004     const gl::Framebuffer *srcFramebuffer = glState.getReadFramebuffer();
1005     FramebufferVk *srcFramebufferVk       = vk::GetImpl(srcFramebuffer);
1006     if (srcFramebufferVk->mDeferredClears.any())
1007     {
1008         srcFramebufferVk->redeferClearsForReadFramebuffer(contextVk);
1009     }
1010 
1011     // We can sometimes end up in a blit with some clear commands saved. Ensure all clear commands
1012     // are issued before we issue the blit command.
1013     ANGLE_TRY(flushDeferredClears(contextVk));
1014 
1015     const bool blitColorBuffer   = (mask & GL_COLOR_BUFFER_BIT) != 0;
1016     const bool blitDepthBuffer   = (mask & GL_DEPTH_BUFFER_BIT) != 0;
1017     const bool blitStencilBuffer = (mask & GL_STENCIL_BUFFER_BIT) != 0;
1018 
1019     // If a framebuffer contains a mixture of multisampled and multisampled-render-to-texture
1020     // attachments, this function could be simultaneously doing a blit on one attachment and resolve
1021     // on another.  For the most part, this means resolve semantics apply.  However, as the resolve
1022     // path cannot be taken for multisampled-render-to-texture attachments, the distinction of
1023     // whether resolve is done for each attachment or blit is made.
1024     const bool isColorResolve =
1025         blitColorBuffer &&
1026         srcFramebufferVk->getColorReadRenderTarget()->getImageForCopy().getSamples() > 1;
1027     const bool isDepthStencilResolve =
1028         (blitDepthBuffer || blitStencilBuffer) &&
1029         srcFramebufferVk->getDepthStencilRenderTarget()->getImageForCopy().getSamples() > 1;
1030     const bool isResolve = isColorResolve || isDepthStencilResolve;
1031 
1032     bool srcFramebufferFlippedY = contextVk->isViewportFlipEnabledForReadFBO();
1033     bool dstFramebufferFlippedY = contextVk->isViewportFlipEnabledForDrawFBO();
1034 
1035     gl::Rectangle sourceArea = sourceAreaIn;
1036     gl::Rectangle destArea   = destAreaIn;
1037 
1038     // Note: GLES (all 3.x versions) require source and destination area to be identical when
1039     // resolving.
1040     ASSERT(!isResolve ||
1041            (sourceArea.x == destArea.x && sourceArea.y == destArea.y &&
1042             sourceArea.width == destArea.width && sourceArea.height == destArea.height));
1043 
1044     gl::Rectangle srcFramebufferDimensions = srcFramebufferVk->getNonRotatedCompleteRenderArea();
1045     gl::Rectangle dstFramebufferDimensions = getNonRotatedCompleteRenderArea();
1046 
1047     // If the destination is flipped in either direction, we will flip the source instead so that
1048     // the destination area is always unflipped.
1049     sourceArea = sourceArea.flip(destArea.isReversedX(), destArea.isReversedY());
1050     destArea   = destArea.removeReversal();
1051 
1052     // Calculate the stretch factor prior to any clipping, as it needs to remain constant.
1053     const double stretch[2] = {
1054         std::abs(sourceArea.width / static_cast<double>(destArea.width)),
1055         std::abs(sourceArea.height / static_cast<double>(destArea.height)),
1056     };
1057 
1058     // Potentially make adjustments for pre-rotatation.  To handle various cases (e.g. clipping)
1059     // and to not interrupt the normal flow of the code, different adjustments are made in
1060     // different parts of the code.  These first adjustments are for whether or not to flip the
1061     // y-axis, and to note the overall rotation (regardless of whether it is the source or
1062     // destination that is rotated).
1063     SurfaceRotation srcFramebufferRotation = contextVk->getRotationReadFramebuffer();
1064     SurfaceRotation dstFramebufferRotation = contextVk->getRotationDrawFramebuffer();
1065     SurfaceRotation rotation               = SurfaceRotation::Identity;
1066     // Both the source and destination cannot be rotated (which would indicate both are the default
1067     // framebuffer (i.e. swapchain image).
1068     ASSERT((srcFramebufferRotation == SurfaceRotation::Identity) ||
1069            (dstFramebufferRotation == SurfaceRotation::Identity));
1070     EarlyAdjustFlipYForPreRotation(srcFramebufferRotation, &rotation, &srcFramebufferFlippedY);
1071     EarlyAdjustFlipYForPreRotation(dstFramebufferRotation, &rotation, &dstFramebufferFlippedY);
1072 
1073     // First, clip the source area to framebuffer.  That requires transforming the destination area
1074     // to match the clipped source.
1075     gl::Rectangle absSourceArea = sourceArea.removeReversal();
1076     gl::Rectangle clippedSourceArea;
1077     if (!gl::ClipRectangle(srcFramebufferDimensions, absSourceArea, &clippedSourceArea))
1078     {
1079         return angle::Result::Continue;
1080     }
1081 
1082     // Resize the destination area based on the new size of source.  Note again that stretch is
1083     // calculated as SrcDimension/DestDimension.
1084     gl::Rectangle srcClippedDestArea;
1085     if (isResolve)
1086     {
1087         // Source and destination areas are identical in resolve (except rotate it, if appropriate).
1088         srcClippedDestArea = clippedSourceArea;
1089         AdjustBlitAreaForPreRotation(dstFramebufferRotation, clippedSourceArea,
1090                                      dstFramebufferDimensions, &srcClippedDestArea);
1091     }
1092     else if (clippedSourceArea == absSourceArea)
1093     {
1094         // If there was no clipping, keep destination area as is (except rotate it, if appropriate).
1095         srcClippedDestArea = destArea;
1096         AdjustBlitAreaForPreRotation(dstFramebufferRotation, destArea, dstFramebufferDimensions,
1097                                      &srcClippedDestArea);
1098     }
1099     else
1100     {
1101         // Shift destination area's x0,y0,x1,y1 by as much as the source area's got shifted (taking
1102         // stretching into account).  Note that double is used as float doesn't have enough
1103         // precision near the end of int range.
1104         double x0Shift = std::round((clippedSourceArea.x - absSourceArea.x) / stretch[0]);
1105         double y0Shift = std::round((clippedSourceArea.y - absSourceArea.y) / stretch[1]);
1106         double x1Shift = std::round((absSourceArea.x1() - clippedSourceArea.x1()) / stretch[0]);
1107         double y1Shift = std::round((absSourceArea.y1() - clippedSourceArea.y1()) / stretch[1]);
1108 
1109         // If the source area was reversed in any direction, the shift should be applied in the
1110         // opposite direction as well.
1111         if (sourceArea.isReversedX())
1112         {
1113             std::swap(x0Shift, x1Shift);
1114         }
1115 
1116         if (sourceArea.isReversedY())
1117         {
1118             std::swap(y0Shift, y1Shift);
1119         }
1120 
1121         srcClippedDestArea.x = destArea.x0() + static_cast<int>(x0Shift);
1122         srcClippedDestArea.y = destArea.y0() + static_cast<int>(y0Shift);
1123         int x1               = destArea.x1() - static_cast<int>(x1Shift);
1124         int y1               = destArea.y1() - static_cast<int>(y1Shift);
1125 
1126         srcClippedDestArea.width  = x1 - srcClippedDestArea.x;
1127         srcClippedDestArea.height = y1 - srcClippedDestArea.y;
1128 
1129         // Rotate srcClippedDestArea if the destination is rotated
1130         if (dstFramebufferRotation != SurfaceRotation::Identity)
1131         {
1132             gl::Rectangle originalSrcClippedDestArea = srcClippedDestArea;
1133             AdjustBlitAreaForPreRotation(dstFramebufferRotation, originalSrcClippedDestArea,
1134                                          dstFramebufferDimensions, &srcClippedDestArea);
1135         }
1136     }
1137 
1138     // If framebuffers are flipped in Y, flip the source and destination area (which define the
1139     // transformation regardless of clipping), as well as the blit area (which is the clipped
1140     // destination area).
1141     if (srcFramebufferFlippedY)
1142     {
1143         sourceArea.y      = srcFramebufferDimensions.height - sourceArea.y;
1144         sourceArea.height = -sourceArea.height;
1145     }
1146     if (dstFramebufferFlippedY)
1147     {
1148         destArea.y      = dstFramebufferDimensions.height - destArea.y;
1149         destArea.height = -destArea.height;
1150 
1151         srcClippedDestArea.y =
1152             dstFramebufferDimensions.height - srcClippedDestArea.y - srcClippedDestArea.height;
1153     }
1154 
1155     bool flipX = sourceArea.isReversedX() != destArea.isReversedX();
1156     bool flipY = sourceArea.isReversedY() != destArea.isReversedY();
1157 
1158     // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve.
1159     ASSERT(!isResolve ||
1160            (flipX == false && flipY == (srcFramebufferFlippedY != dstFramebufferFlippedY)));
1161 
1162     // Again, transfer the destination flip to source, so destination is unflipped.  Note that
1163     // destArea was not reversed until the final possible Y-flip.
1164     ASSERT(!destArea.isReversedX());
1165     sourceArea = sourceArea.flip(false, destArea.isReversedY());
1166     destArea   = destArea.removeReversal();
1167 
1168     // Now that clipping and flipping is done, rotate certain values that will be used for
1169     // UtilsVk::BlitResolveParameters
1170     gl::Rectangle sourceAreaOld = sourceArea;
1171     gl::Rectangle destAreaOld   = destArea;
1172     if (srcFramebufferRotation == rotation)
1173     {
1174         AdjustBlitAreaForPreRotation(srcFramebufferRotation, sourceAreaOld,
1175                                      srcFramebufferDimensions, &sourceArea);
1176         AdjustDimensionsAndFlipForPreRotation(srcFramebufferRotation, &srcFramebufferDimensions,
1177                                               &flipX, &flipY);
1178     }
1179     SurfaceRotation rememberDestFramebufferRotation = dstFramebufferRotation;
1180     if (srcFramebufferRotation == SurfaceRotation::Rotated90Degrees)
1181     {
1182         dstFramebufferRotation = rotation;
1183     }
1184     AdjustBlitAreaForPreRotation(dstFramebufferRotation, destAreaOld, dstFramebufferDimensions,
1185                                  &destArea);
1186     dstFramebufferRotation = rememberDestFramebufferRotation;
1187 
1188     // Clip the destination area to the framebuffer size and scissor.  Note that we don't care
1189     // about the source area anymore.  The offset translation is done based on the original source
1190     // and destination rectangles.  The stretch factor is already calculated as well.
1191     gl::Rectangle blitArea;
1192     if (!gl::ClipRectangle(getRotatedScissoredRenderArea(contextVk), srcClippedDestArea, &blitArea))
1193     {
1194         return angle::Result::Continue;
1195     }
1196 
1197     bool noClip = blitArea == destArea && stretch[0] == 1.0f && stretch[1] == 1.0f;
1198     bool noFlip = !flipX && !flipY;
1199     bool disableFlippingBlitWithCommand =
1200         contextVk->getRenderer()->getFeatures().disableFlippingBlitWithCommand.enabled;
1201 
1202     UtilsVk::BlitResolveParameters commonParams;
1203     commonParams.srcOffset[0]           = sourceArea.x;
1204     commonParams.srcOffset[1]           = sourceArea.y;
1205     commonParams.dstOffset[0]           = destArea.x;
1206     commonParams.dstOffset[1]           = destArea.y;
1207     commonParams.rotatedOffsetFactor[0] = std::abs(sourceArea.width);
1208     commonParams.rotatedOffsetFactor[1] = std::abs(sourceArea.height);
1209     commonParams.stretch[0]             = static_cast<float>(stretch[0]);
1210     commonParams.stretch[1]             = static_cast<float>(stretch[1]);
1211     commonParams.srcExtents[0]          = srcFramebufferDimensions.width;
1212     commonParams.srcExtents[1]          = srcFramebufferDimensions.height;
1213     commonParams.blitArea               = blitArea;
1214     commonParams.linear                 = filter == GL_LINEAR && !isResolve;
1215     commonParams.flipX                  = flipX;
1216     commonParams.flipY                  = flipY;
1217     commonParams.rotation               = rotation;
1218 
1219     if (blitColorBuffer)
1220     {
1221         RenderTargetVk *readRenderTarget      = srcFramebufferVk->getColorReadRenderTarget();
1222         UtilsVk::BlitResolveParameters params = commonParams;
1223         params.srcLayer                       = readRenderTarget->getLayerIndex();
1224 
1225         // Multisampled images are not allowed to have mips.
1226         ASSERT(!isColorResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));
1227 
1228         // If there was no clipping and the format capabilities allow us, use Vulkan's builtin blit.
1229         // The reason clipping is prohibited in this path is that due to rounding errors, it would
1230         // be hard to guarantee the image stretching remains perfect.  That also allows us not to
1231         // have to transform back the destination clipping to source.
1232         //
1233         // Non-identity pre-rotation cases do not use Vulkan's builtin blit.
1234         //
1235         // For simplicity, we either blit all render targets with a Vulkan command, or none.
1236         bool canBlitWithCommand =
1237             !isColorResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) &&
1238             HasSrcBlitFeature(renderer, readRenderTarget) && rotation == SurfaceRotation::Identity;
1239         // If we need to reinterpret the colorspace then the blit must be done through a shader
1240         bool reinterpretsColorspace =
1241             mCurrentFramebufferDesc.getWriteControlMode() != gl::SrgbWriteControlMode::Default;
1242         bool areChannelsBlitCompatible = true;
1243         bool areFormatsIdentical       = true;
1244         for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1245         {
1246             RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1247             canBlitWithCommand =
1248                 canBlitWithCommand && HasDstBlitFeature(renderer, drawRenderTarget);
1249             areChannelsBlitCompatible =
1250                 areChannelsBlitCompatible &&
1251                 AreSrcAndDstColorChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
1252             areFormatsIdentical = areFormatsIdentical &&
1253                                   AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget);
1254         }
1255 
1256         // Now that all flipping is done, adjust the offsets for resolve and prerotation
1257         if (isColorResolve)
1258         {
1259             AdjustBlitResolveParametersForResolve(sourceArea, destArea, &params);
1260         }
1261         AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, &params);
1262 
1263         if (canBlitWithCommand && areChannelsBlitCompatible && !reinterpretsColorspace)
1264         {
1265             for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1266             {
1267                 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1268                 ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
1269                                           drawRenderTarget, filter, true, false, false, flipX,
1270                                           flipY));
1271             }
1272         }
1273         // If we're not flipping or rotating, use Vulkan's builtin resolve.
1274         else if (isColorResolve && !flipX && !flipY && areChannelsBlitCompatible &&
1275                  areFormatsIdentical && rotation == SurfaceRotation::Identity &&
1276                  !reinterpretsColorspace)
1277         {
1278             // Resolving with a subpass resolve attachment has a few restrictions:
1279             // 1.) glBlitFramebuffer() needs to copy the read color attachment to all enabled
1280             // attachments in the draw framebuffer, but Vulkan requires a 1:1 relationship for
1281             // multisample attachments to resolve attachments in the render pass subpass.
1282             // Due to this, we currently only support using resolve attachments when there is a
1283             // single draw attachment enabled.
1284             // 2.) Using a subpass resolve attachment relies on using the render pass that performs
1285             // the draw to still be open, so it can be updated to use the resolve attachment to draw
1286             // into. If there's no render pass with commands, then the multisampled render pass is
1287             // already done and whose data is already flushed from the tile (in a tile-based
1288             // renderer), so there's no chance for the resolve attachment to take advantage of the
1289             // data already being present in the tile.
1290 
1291             // TODO(https://anglebug.com/4968): Support multiple open render passes so we can remove
1292             //  this hack to 'restore' the finished render pass.
1293             // TODO(https://anglebug.com/7553): Look into optimization below in order to remove the
1294             //  check of whether the current framebuffer is valid.
1295             bool isCurrentFramebufferValid = srcFramebufferVk->mCurrentFramebuffer.valid();
1296 
1297             // glBlitFramebuffer() needs to copy the read color attachment to all enabled
1298             // attachments in the draw framebuffer, but Vulkan requires a 1:1 relationship for
1299             // multisample attachments to resolve attachments in the render pass subpass.  Due to
1300             // this, we currently only support using resolve attachments when there is a single draw
1301             // attachment enabled.
1302             bool canResolveWithSubpass = isCurrentFramebufferValid &&
1303                                          mState.getEnabledDrawBuffers().count() == 1 &&
1304                                          mCurrentFramebufferDesc.getLayerCount() == 1 &&
1305                                          contextVk->hasStartedRenderPassWithQueueSerial(
1306                                              srcFramebufferVk->getLastRenderPassQueueSerial());
1307 
1308             // Additionally, when resolving with a resolve attachment, the src and destination
1309             // offsets must match, the render area must match the resolve area, and there should be
1310             // no flipping or rotation.  Fortunately, in GLES the blit source and destination areas
1311             // are already required to be identical.
1312             ASSERT(params.srcOffset[0] == params.dstOffset[0] &&
1313                    params.srcOffset[1] == params.dstOffset[1]);
1314             canResolveWithSubpass =
1315                 canResolveWithSubpass && noFlip && rotation == SurfaceRotation::Identity &&
1316                 blitArea == contextVk->getStartedRenderPassCommands().getRenderArea();
1317 
1318             if (canResolveWithSubpass)
1319             {
1320                 ANGLE_TRY(resolveColorWithSubpass(contextVk, params));
1321             }
1322             else
1323             {
1324                 ANGLE_TRY(resolveColorWithCommand(contextVk, params,
1325                                                   &readRenderTarget->getImageForCopy()));
1326             }
1327         }
1328         // Otherwise use a shader to do blit or resolve.
1329         else
1330         {
1331             // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
1332             // Otherwise the view serials would not reflect the render pass they are really used in.
1333             // http://crbug.com/1272266#c22
1334             ANGLE_TRY(
1335                 contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForBlit));
1336 
1337             const vk::ImageView *copyImageView = nullptr;
1338             ANGLE_TRY(readRenderTarget->getCopyImageView(contextVk, &copyImageView));
1339             ANGLE_TRY(utilsVk.colorBlitResolve(
1340                 contextVk, this, &readRenderTarget->getImageForCopy(), copyImageView, params));
1341         }
1342     }
1343 
1344     if (blitDepthBuffer || blitStencilBuffer)
1345     {
1346         RenderTargetVk *readRenderTarget      = srcFramebufferVk->getDepthStencilRenderTarget();
1347         RenderTargetVk *drawRenderTarget      = mRenderTargetCache.getDepthStencil();
1348         UtilsVk::BlitResolveParameters params = commonParams;
1349         params.srcLayer                       = readRenderTarget->getLayerIndex();
1350 
1351         // Multisampled images are not allowed to have mips.
1352         ASSERT(!isDepthStencilResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));
1353 
1354         // Similarly, only blit if there's been no clipping or rotating.
1355         bool canBlitWithCommand =
1356             !isDepthStencilResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) &&
1357             HasSrcBlitFeature(renderer, readRenderTarget) &&
1358             HasDstBlitFeature(renderer, drawRenderTarget) && rotation == SurfaceRotation::Identity;
1359         bool areChannelsBlitCompatible =
1360             AreSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
1361 
1362         // glBlitFramebuffer requires that depth/stencil blits have matching formats.
1363         ASSERT(AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget));
1364 
1365         if (canBlitWithCommand && areChannelsBlitCompatible)
1366         {
1367             ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
1368                                       drawRenderTarget, filter, false, blitDepthBuffer,
1369                                       blitStencilBuffer, flipX, flipY));
1370         }
1371         else
1372         {
1373             // Now that all flipping is done, adjust the offsets for resolve and prerotation
1374             if (isDepthStencilResolve)
1375             {
1376                 AdjustBlitResolveParametersForResolve(sourceArea, destArea, &params);
1377             }
1378             AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, &params);
1379 
1380             // Create depth- and stencil-only views for reading.
1381             vk::DeviceScoped<vk::ImageView> depthView(contextVk->getDevice());
1382             vk::DeviceScoped<vk::ImageView> stencilView(contextVk->getDevice());
1383 
1384             vk::ImageHelper *depthStencilImage = &readRenderTarget->getImageForCopy();
1385             vk::LevelIndex levelIndex =
1386                 depthStencilImage->toVkLevel(readRenderTarget->getLevelIndex());
1387             uint32_t layerIndex         = readRenderTarget->getLayerIndex();
1388             gl::TextureType textureType = vk::Get2DTextureType(depthStencilImage->getLayerCount(),
1389                                                                depthStencilImage->getSamples());
1390 
1391             if (blitDepthBuffer)
1392             {
1393                 ANGLE_TRY(depthStencilImage->initLayerImageView(
1394                     contextVk, textureType, VK_IMAGE_ASPECT_DEPTH_BIT, gl::SwizzleState(),
1395                     &depthView.get(), levelIndex, 1, layerIndex, 1,
1396                     gl::SrgbWriteControlMode::Default, gl::YuvSamplingMode::Default,
1397                     vk::ImageHelper::kDefaultImageViewUsageFlags));
1398             }
1399 
1400             if (blitStencilBuffer)
1401             {
1402                 ANGLE_TRY(depthStencilImage->initLayerImageView(
1403                     contextVk, textureType, VK_IMAGE_ASPECT_STENCIL_BIT, gl::SwizzleState(),
1404                     &stencilView.get(), levelIndex, 1, layerIndex, 1,
1405                     gl::SrgbWriteControlMode::Default, gl::YuvSamplingMode::Default,
1406                     vk::ImageHelper::kDefaultImageViewUsageFlags));
1407             }
1408 
1409             // If shader stencil export is not possible, defer stencil blit/resolve to another pass.
1410             bool hasShaderStencilExport =
1411                 contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled;
1412 
1413             // Blit depth. If shader stencil export is present, blit stencil as well.
1414             if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport))
1415             {
1416                 const vk::ImageView *depth = blitDepthBuffer ? &depthView.get() : nullptr;
1417                 const vk::ImageView *stencil =
1418                     blitStencilBuffer && hasShaderStencilExport ? &stencilView.get() : nullptr;
1419 
1420                 ANGLE_TRY(utilsVk.depthStencilBlitResolve(contextVk, this, depthStencilImage, depth,
1421                                                           stencil, params));
1422             }
1423 
1424             // If shader stencil export is not present, blit stencil through a different path.
1425             if (blitStencilBuffer && !hasShaderStencilExport)
1426             {
1427                 ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW,
1428                                       "Inefficient BlitFramebuffer operation on the stencil aspect "
1429                                       "due to lack of shader stencil export support");
1430                 ANGLE_TRY(utilsVk.stencilBlitResolveNoShaderExport(
1431                     contextVk, this, depthStencilImage, &stencilView.get(), params));
1432             }
1433 
1434             vk::ImageView depthViewObject   = depthView.release();
1435             vk::ImageView stencilViewObject = stencilView.release();
1436 
1437             contextVk->addGarbage(&depthViewObject);
1438             contextVk->addGarbage(&stencilViewObject);
1439         }
1440     }
1441 
1442     return angle::Result::Continue;
1443 }
1444 
updateColorResolveAttachment(uint32_t colorIndexGL,vk::ImageOrBufferViewSubresourceSerial resolveImageViewSerial)1445 void FramebufferVk::updateColorResolveAttachment(
1446     uint32_t colorIndexGL,
1447     vk::ImageOrBufferViewSubresourceSerial resolveImageViewSerial)
1448 {
1449     mCurrentFramebufferDesc.updateColorResolve(colorIndexGL, resolveImageViewSerial);
1450     mRenderPassDesc.packColorResolveAttachment(colorIndexGL);
1451 }
1452 
removeColorResolveAttachment(uint32_t colorIndexGL)1453 void FramebufferVk::removeColorResolveAttachment(uint32_t colorIndexGL)
1454 {
1455     mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
1456                                                vk::kInvalidImageOrBufferViewSubresourceSerial);
1457     mRenderPassDesc.removeColorResolveAttachment(colorIndexGL);
1458 }
1459 
releaseCurrentFramebuffer(ContextVk * contextVk)1460 void FramebufferVk::releaseCurrentFramebuffer(ContextVk *contextVk)
1461 {
1462     if (mIsCurrentFramebufferCached)
1463     {
1464         mCurrentFramebuffer.release();
1465     }
1466     else
1467     {
1468         contextVk->addGarbage(&mCurrentFramebuffer);
1469     }
1470 }
1471 
updateLayerCount()1472 void FramebufferVk::updateLayerCount()
1473 {
1474     uint32_t layerCount = std::numeric_limits<uint32_t>::max();
1475 
1476     // Color attachments.
1477     const auto &colorRenderTargets = mRenderTargetCache.getColors();
1478     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
1479     {
1480         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1481         ASSERT(colorRenderTarget);
1482         layerCount = std::min(layerCount, colorRenderTarget->getLayerCount());
1483     }
1484 
1485     // Depth/stencil attachment.
1486     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
1487     if (depthStencilRenderTarget)
1488     {
1489         layerCount = std::min(layerCount, depthStencilRenderTarget->getLayerCount());
1490     }
1491 
1492     if (layerCount == std::numeric_limits<uint32_t>::max())
1493     {
1494         layerCount = mState.getDefaultLayers();
1495     }
1496 
1497     // While layer count and view count are mutually exclusive, they result in different render
1498     // passes (and thus framebuffers).  For multiview, layer count is set to view count and a flag
1499     // signifies that the framebuffer is multiview (as opposed to layered).
1500     const bool isMultiview = mState.isMultiview();
1501     if (isMultiview)
1502     {
1503         layerCount = mState.getNumViews();
1504     }
1505 
1506     mCurrentFramebufferDesc.updateLayerCount(layerCount);
1507     mCurrentFramebufferDesc.updateIsMultiview(isMultiview);
1508 }
1509 
resolveColorWithSubpass(ContextVk * contextVk,const UtilsVk::BlitResolveParameters & params)1510 angle::Result FramebufferVk::resolveColorWithSubpass(ContextVk *contextVk,
1511                                                      const UtilsVk::BlitResolveParameters &params)
1512 {
1513     // Vulkan requires a 1:1 relationship for multisample attachments to resolve attachments in the
1514     // render pass subpass. Due to this, we currently only support using resolve attachments when
1515     // there is a single draw attachment enabled.
1516     ASSERT(mState.getEnabledDrawBuffers().count() == 1);
1517     uint32_t drawColorIndexGL = static_cast<uint32_t>(*mState.getEnabledDrawBuffers().begin());
1518 
1519     const gl::State &glState              = contextVk->getState();
1520     const gl::Framebuffer *srcFramebuffer = glState.getReadFramebuffer();
1521     FramebufferVk *srcFramebufferVk       = vk::GetImpl(srcFramebuffer);
1522     uint32_t readColorIndexGL             = srcFramebuffer->getState().getReadIndex();
1523 
1524     // Use the draw FBO's color attachments as resolve attachments in the read FBO.
1525     // - Assign the draw FBO's color attachment Serial to the read FBO's resolve attachment
1526     // - Deactivate the source Framebuffer, since the description changed
1527     // - Update the renderpass description to indicate there's a resolve attachment
1528     vk::ImageOrBufferViewSubresourceSerial resolveImageViewSerial =
1529         mCurrentFramebufferDesc.getColorImageViewSerial(drawColorIndexGL);
1530     ASSERT(resolveImageViewSerial.viewSerial.valid());
1531     srcFramebufferVk->updateColorResolveAttachment(readColorIndexGL, resolveImageViewSerial);
1532     srcFramebufferVk->releaseCurrentFramebuffer(contextVk);
1533 
1534     // Since the source FBO was updated with a resolve attachment it didn't have when the render
1535     // pass was started, we need to:
1536     // 1. Get the new framebuffer
1537     //   - The draw framebuffer's ImageView will be used as the resolve attachment, so pass it along
1538     //   in case vkCreateFramebuffer() needs to be called to create a new vkFramebuffer with the new
1539     //   resolve attachment.
1540     RenderTargetVk *drawRenderTarget      = mRenderTargetCache.getColors()[drawColorIndexGL];
1541     const vk::ImageView *resolveImageView = nullptr;
1542     ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &resolveImageView));
1543     vk::MaybeImagelessFramebuffer newSrcFramebuffer = {};
1544     ANGLE_TRY(srcFramebufferVk->getFramebuffer(contextVk, &newSrcFramebuffer, drawRenderTarget,
1545                                                resolveImageView, SwapchainResolveMode::Disabled));
1546     // 2. Update the RenderPassCommandBufferHelper with the new framebuffer and render pass
1547     vk::RenderPassCommandBufferHelper &commandBufferHelper =
1548         contextVk->getStartedRenderPassCommands();
1549     commandBufferHelper.updateRenderPassForResolve(contextVk, newSrcFramebuffer,
1550                                                    srcFramebufferVk->getRenderPassDesc());
1551 
1552     // End the render pass now since we don't (yet) support subpass dependencies.
1553     drawRenderTarget->onColorResolve(contextVk, mCurrentFramebufferDesc.getLayerCount());
1554     ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
1555         RenderPassClosureReason::AlreadySpecifiedElsewhere));
1556 
1557     // Remove the resolve attachment from the source framebuffer.
1558     srcFramebufferVk->removeColorResolveAttachment(readColorIndexGL);
1559     srcFramebufferVk->releaseCurrentFramebuffer(contextVk);
1560 
1561     return angle::Result::Continue;
1562 }
1563 
resolveColorWithCommand(ContextVk * contextVk,const UtilsVk::BlitResolveParameters & params,vk::ImageHelper * srcImage)1564 angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
1565                                                      const UtilsVk::BlitResolveParameters &params,
1566                                                      vk::ImageHelper *srcImage)
1567 {
1568     vk::CommandBufferAccess access;
1569     access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
1570 
1571     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1572     {
1573         RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1574         vk::ImageHelper &dstImage        = drawRenderTarget->getImageForWrite();
1575 
1576         access.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
1577                                     drawRenderTarget->getLayerIndex(), 1, VK_IMAGE_ASPECT_COLOR_BIT,
1578                                     &dstImage);
1579     }
1580 
1581     vk::OutsideRenderPassCommandBuffer *commandBuffer;
1582     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1583 
1584     VkImageResolve resolveRegion                = {};
1585     resolveRegion.srcSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
1586     resolveRegion.srcSubresource.mipLevel       = 0;
1587     resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
1588     resolveRegion.srcSubresource.layerCount     = 1;
1589     resolveRegion.srcOffset.x                   = params.blitArea.x;
1590     resolveRegion.srcOffset.y                   = params.blitArea.y;
1591     resolveRegion.srcOffset.z                   = 0;
1592     resolveRegion.dstSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
1593     resolveRegion.dstSubresource.layerCount     = 1;
1594     resolveRegion.dstOffset.x                   = params.blitArea.x;
1595     resolveRegion.dstOffset.y                   = params.blitArea.y;
1596     resolveRegion.dstOffset.z                   = 0;
1597     resolveRegion.extent.width                  = params.blitArea.width;
1598     resolveRegion.extent.height                 = params.blitArea.height;
1599     resolveRegion.extent.depth                  = 1;
1600 
1601     angle::VulkanPerfCounters &perfCounters = contextVk->getPerfCounters();
1602     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1603     {
1604         RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1605         vk::ImageHelper &dstImage        = drawRenderTarget->getImageForWrite();
1606 
1607         vk::LevelIndex levelVk = dstImage.toVkLevel(drawRenderTarget->getLevelIndex());
1608         resolveRegion.dstSubresource.mipLevel       = levelVk.get();
1609         resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
1610 
1611         srcImage->resolve(&dstImage, resolveRegion, commandBuffer);
1612 
1613         perfCounters.resolveImageCommands++;
1614     }
1615 
1616     return angle::Result::Continue;
1617 }
1618 
checkStatus(const gl::Context * context) const1619 gl::FramebufferStatus FramebufferVk::checkStatus(const gl::Context *context) const
1620 {
1621     // if we have both a depth and stencil buffer, they must refer to the same object
1622     // since we only support packed_depth_stencil and not separate depth and stencil
1623     if (mState.hasSeparateDepthAndStencilAttachments())
1624     {
1625         return gl::FramebufferStatus::Incomplete(
1626             GL_FRAMEBUFFER_UNSUPPORTED,
1627             gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
1628     }
1629 
1630     return gl::FramebufferStatus::Complete();
1631 }
1632 
invalidateImpl(ContextVk * contextVk,size_t count,const GLenum * attachments,bool isSubInvalidate,const gl::Rectangle & invalidateArea)1633 angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
1634                                             size_t count,
1635                                             const GLenum *attachments,
1636                                             bool isSubInvalidate,
1637                                             const gl::Rectangle &invalidateArea)
1638 {
1639     gl::DrawBufferMask invalidateColorBuffers;
1640     bool invalidateDepthBuffer   = false;
1641     bool invalidateStencilBuffer = false;
1642 
1643     for (size_t i = 0; i < count; ++i)
1644     {
1645         const GLenum attachment = attachments[i];
1646 
1647         switch (attachment)
1648         {
1649             case GL_DEPTH:
1650             case GL_DEPTH_ATTACHMENT:
1651                 invalidateDepthBuffer = true;
1652                 break;
1653             case GL_STENCIL:
1654             case GL_STENCIL_ATTACHMENT:
1655                 invalidateStencilBuffer = true;
1656                 break;
1657             case GL_DEPTH_STENCIL_ATTACHMENT:
1658                 invalidateDepthBuffer   = true;
1659                 invalidateStencilBuffer = true;
1660                 break;
1661             default:
1662                 ASSERT(
1663                     (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) ||
1664                     (attachment == GL_COLOR));
1665 
1666                 invalidateColorBuffers.set(
1667                     attachment == GL_COLOR ? 0u : (attachment - GL_COLOR_ATTACHMENT0));
1668         }
1669     }
1670 
1671     // Shouldn't try to issue deferred clears if invalidating sub framebuffer.
1672     ASSERT(mDeferredClears.empty() || !isSubInvalidate);
1673 
1674     // Remove deferred clears for the invalidated attachments.
1675     if (invalidateDepthBuffer)
1676     {
1677         mDeferredClears.reset(vk::kUnpackedDepthIndex);
1678     }
1679     if (invalidateStencilBuffer)
1680     {
1681         mDeferredClears.reset(vk::kUnpackedStencilIndex);
1682     }
1683     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1684     {
1685         if (invalidateColorBuffers.test(colorIndexGL))
1686         {
1687             mDeferredClears.reset(colorIndexGL);
1688         }
1689     }
1690 
1691     // If there are still deferred clears, redefer them.  See relevant comment in invalidateSub.
1692     redeferClears(contextVk);
1693 
1694     const auto &colorRenderTargets           = mRenderTargetCache.getColors();
1695     RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
1696 
1697     // If not a partial invalidate, mark the contents of the invalidated attachments as undefined,
1698     // so their loadOp can be set to DONT_CARE in the following render pass.
1699     if (!isSubInvalidate)
1700     {
1701         for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1702         {
1703             if (invalidateColorBuffers.test(colorIndexGL))
1704             {
1705                 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1706                 ASSERT(colorRenderTarget);
1707 
1708                 bool preferToKeepContentsDefined = false;
1709                 colorRenderTarget->invalidateEntireContent(contextVk, &preferToKeepContentsDefined);
1710                 if (preferToKeepContentsDefined)
1711                 {
1712                     invalidateColorBuffers.reset(colorIndexGL);
1713                 }
1714             }
1715         }
1716 
1717         // If we have a depth / stencil render target, invalidate its aspects.
1718         if (depthStencilRenderTarget)
1719         {
1720             if (invalidateDepthBuffer)
1721             {
1722                 bool preferToKeepContentsDefined = false;
1723                 depthStencilRenderTarget->invalidateEntireContent(contextVk,
1724                                                                   &preferToKeepContentsDefined);
1725                 if (preferToKeepContentsDefined)
1726                 {
1727                     invalidateDepthBuffer = false;
1728                 }
1729             }
1730             if (invalidateStencilBuffer)
1731             {
1732                 bool preferToKeepContentsDefined = false;
1733                 depthStencilRenderTarget->invalidateEntireStencilContent(
1734                     contextVk, &preferToKeepContentsDefined);
1735                 if (preferToKeepContentsDefined)
1736                 {
1737                     invalidateStencilBuffer = false;
1738                 }
1739             }
1740         }
1741     }
1742 
1743     // To ensure we invalidate the right renderpass we require that the current framebuffer be the
1744     // same as the current renderpass' framebuffer. E.g. prevent sequence like:
1745     //- Bind FBO 1, draw
1746     //- Bind FBO 2, draw
1747     //- Bind FBO 1, invalidate D/S
1748     // to invalidate the D/S of FBO 2 since it would be the currently active renderpass.
1749     if (contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial))
1750     {
1751         // Mark the invalidated attachments in the render pass for loadOp and storeOp determination
1752         // at its end.
1753         vk::PackedAttachmentIndex colorIndexVk(0);
1754         for (size_t colorIndexGL : mState.getColorAttachmentsMask())
1755         {
1756             if (mState.getEnabledDrawBuffers()[colorIndexGL] &&
1757                 invalidateColorBuffers.test(colorIndexGL))
1758             {
1759                 contextVk->getStartedRenderPassCommands().invalidateRenderPassColorAttachment(
1760                     contextVk->getState(), colorIndexGL, colorIndexVk, invalidateArea);
1761             }
1762             ++colorIndexVk;
1763         }
1764 
1765         if (depthStencilRenderTarget)
1766         {
1767             const gl::DepthStencilState &dsState = contextVk->getState().getDepthStencilState();
1768             if (invalidateDepthBuffer)
1769             {
1770                 contextVk->getStartedRenderPassCommands().invalidateRenderPassDepthAttachment(
1771                     dsState, invalidateArea);
1772             }
1773 
1774             if (invalidateStencilBuffer)
1775             {
1776                 contextVk->getStartedRenderPassCommands().invalidateRenderPassStencilAttachment(
1777                     dsState, invalidateArea);
1778             }
1779         }
1780         if (invalidateColorBuffers.any())
1781         {
1782             // Only end the render pass if invalidating at least one color buffer.  Do not end the
1783             // render pass if only the depth and/or stencil buffer is invalidated.  At least one
1784             // application invalidates those every frame, disables depth, and then continues to
1785             // draw only to the color buffer.
1786             //
1787             // Since we are not aware of any application that invalidates a color buffer and
1788             // continues to draw to it, we leave that unoptimized.
1789             ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
1790                 RenderPassClosureReason::ColorBufferInvalidate));
1791         }
1792     }
1793 
1794     return angle::Result::Continue;
1795 }
1796 
updateColorAttachment(const gl::Context * context,uint32_t colorIndexGL)1797 angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context,
1798                                                    uint32_t colorIndexGL)
1799 {
1800     ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndexGL));
1801 
1802     // Update cached masks for masked clears.
1803     RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1804     if (renderTarget)
1805     {
1806         const angle::Format &actualFormat = renderTarget->getImageActualFormat();
1807         updateActiveColorMasks(colorIndexGL, actualFormat.redBits > 0, actualFormat.greenBits > 0,
1808                                actualFormat.blueBits > 0, actualFormat.alphaBits > 0);
1809 
1810         const angle::Format &intendedFormat = renderTarget->getImageIntendedFormat();
1811         mEmulatedAlphaAttachmentMask.set(
1812             colorIndexGL, intendedFormat.alphaBits == 0 && actualFormat.alphaBits > 0);
1813     }
1814     else
1815     {
1816         updateActiveColorMasks(colorIndexGL, false, false, false, false);
1817     }
1818 
1819     const bool enabledColor =
1820         renderTarget && mState.getColorAttachments()[colorIndexGL].isAttached();
1821     const bool enabledResolve = enabledColor && renderTarget->hasResolveAttachment();
1822 
1823     if (enabledColor)
1824     {
1825         mCurrentFramebufferDesc.updateColor(colorIndexGL, renderTarget->getDrawSubresourceSerial());
1826         const bool isExternalImage =
1827             mState.getColorAttachments()[colorIndexGL].isExternalImageWithoutIndividualSync();
1828         mIsExternalColorAttachments.set(colorIndexGL, isExternalImage);
1829         mAttachmentHasFrontBufferUsage.set(
1830             colorIndexGL, mState.getColorAttachments()[colorIndexGL].hasFrontBufferUsage());
1831     }
1832     else
1833     {
1834         mCurrentFramebufferDesc.updateColor(colorIndexGL,
1835                                             vk::kInvalidImageOrBufferViewSubresourceSerial);
1836     }
1837 
1838     if (enabledResolve)
1839     {
1840         mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
1841                                                    renderTarget->getResolveSubresourceSerial());
1842     }
1843     else
1844     {
1845         mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
1846                                                    vk::kInvalidImageOrBufferViewSubresourceSerial);
1847     }
1848 
1849     return angle::Result::Continue;
1850 }
1851 
updateDepthStencilAttachment(const gl::Context * context)1852 angle::Result FramebufferVk::updateDepthStencilAttachment(const gl::Context *context)
1853 {
1854     ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
1855 
1856     ContextVk *contextVk = vk::GetImpl(context);
1857     updateDepthStencilAttachmentSerial(contextVk);
1858 
1859     return angle::Result::Continue;
1860 }
1861 
updateDepthStencilAttachmentSerial(ContextVk * contextVk)1862 void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
1863 {
1864     RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
1865 
1866     if (depthStencilRT != nullptr)
1867     {
1868         mCurrentFramebufferDesc.updateDepthStencil(depthStencilRT->getDrawSubresourceSerial());
1869     }
1870     else
1871     {
1872         mCurrentFramebufferDesc.updateDepthStencil(vk::kInvalidImageOrBufferViewSubresourceSerial);
1873     }
1874 
1875     if (depthStencilRT != nullptr && depthStencilRT->hasResolveAttachment())
1876     {
1877         mCurrentFramebufferDesc.updateDepthStencilResolve(
1878             depthStencilRT->getResolveSubresourceSerial());
1879     }
1880     else
1881     {
1882         mCurrentFramebufferDesc.updateDepthStencilResolve(
1883             vk::kInvalidImageOrBufferViewSubresourceSerial);
1884     }
1885 }
1886 
flushColorAttachmentUpdates(const gl::Context * context,bool deferClears,uint32_t colorIndexGL)1887 angle::Result FramebufferVk::flushColorAttachmentUpdates(const gl::Context *context,
1888                                                          bool deferClears,
1889                                                          uint32_t colorIndexGL)
1890 {
1891     ContextVk *contextVk             = vk::GetImpl(context);
1892     RenderTargetVk *readRenderTarget = nullptr;
1893     RenderTargetVk *drawRenderTarget = nullptr;
1894 
1895     // It's possible for the read and draw color attachments to be different if different surfaces
1896     // are bound, so we need to flush any staged updates to both.
1897 
1898     // Draw
1899     drawRenderTarget = mRenderTargetCache.getColorDraw(mState, colorIndexGL);
1900     if (drawRenderTarget)
1901     {
1902         if (deferClears)
1903         {
1904             ANGLE_TRY(
1905                 drawRenderTarget->flushStagedUpdates(contextVk, &mDeferredClears, colorIndexGL,
1906                                                      mCurrentFramebufferDesc.getLayerCount()));
1907         }
1908         else
1909         {
1910             ANGLE_TRY(drawRenderTarget->flushStagedUpdates(
1911                 contextVk, nullptr, 0, mCurrentFramebufferDesc.getLayerCount()));
1912         }
1913     }
1914 
1915     // Read
1916     if (mState.getReadBufferState() != GL_NONE && mState.getReadIndex() == colorIndexGL)
1917     {
1918         // Flush staged updates to the read render target as well, but only if it's not the same as
1919         // the draw render target.  This can happen when the read render target is bound to another
1920         // surface.
1921         readRenderTarget = mRenderTargetCache.getColorRead(mState);
1922         if (readRenderTarget && readRenderTarget != drawRenderTarget)
1923         {
1924             ANGLE_TRY(readRenderTarget->flushStagedUpdates(
1925                 contextVk, nullptr, 0, mCurrentFramebufferDesc.getLayerCount()));
1926         }
1927     }
1928 
1929     return angle::Result::Continue;
1930 }
1931 
flushDepthStencilAttachmentUpdates(const gl::Context * context,bool deferClears)1932 angle::Result FramebufferVk::flushDepthStencilAttachmentUpdates(const gl::Context *context,
1933                                                                 bool deferClears)
1934 {
1935     ContextVk *contextVk = vk::GetImpl(context);
1936 
1937     RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
1938     if (depthStencilRT == nullptr)
1939     {
1940         return angle::Result::Continue;
1941     }
1942 
1943     if (deferClears)
1944     {
1945         return depthStencilRT->flushStagedUpdates(contextVk, &mDeferredClears,
1946                                                   vk::kUnpackedDepthIndex,
1947                                                   mCurrentFramebufferDesc.getLayerCount());
1948     }
1949 
1950     return depthStencilRT->flushStagedUpdates(contextVk, nullptr, 0,
1951                                               mCurrentFramebufferDesc.getLayerCount());
1952 }
1953 
syncState(const gl::Context * context,GLenum binding,const gl::Framebuffer::DirtyBits & dirtyBits,gl::Command command)1954 angle::Result FramebufferVk::syncState(const gl::Context *context,
1955                                        GLenum binding,
1956                                        const gl::Framebuffer::DirtyBits &dirtyBits,
1957                                        gl::Command command)
1958 {
1959     ContextVk *contextVk = vk::GetImpl(context);
1960 
1961     vk::FramebufferDesc priorFramebufferDesc = mCurrentFramebufferDesc;
1962 
1963     // Keep track of which attachments have dirty content and need their staged updates flushed.
1964     // The respective functions depend on |mCurrentFramebufferDesc::mLayerCount| which is updated
1965     // after all attachment render targets are updated.
1966     gl::DrawBufferMask dirtyColorAttachments;
1967     bool dirtyDepthStencilAttachment = false;
1968 
1969     bool shouldUpdateColorMaskAndBlend    = false;
1970     bool shouldUpdateLayerCount           = false;
1971     bool shouldUpdateSrgbWriteControlMode = false;
1972 
1973     // For any updated attachments we'll update their Serials below
1974     ASSERT(dirtyBits.any());
1975     for (size_t dirtyBit : dirtyBits)
1976     {
1977         switch (dirtyBit)
1978         {
1979             case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
1980             case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS:
1981             case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
1982             case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS:
1983                 ANGLE_TRY(updateDepthStencilAttachment(context));
1984                 shouldUpdateLayerCount      = true;
1985                 dirtyDepthStencilAttachment = true;
1986                 break;
1987             case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
1988                 ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
1989                 break;
1990             case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
1991                 shouldUpdateColorMaskAndBlend = true;
1992                 shouldUpdateLayerCount        = true;
1993                 break;
1994             case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
1995             case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
1996             case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
1997             case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1998                 // Invalidate the cache. If we have performance critical code hitting this path we
1999                 // can add related data (such as width/height) to the cache
2000                 releaseCurrentFramebuffer(contextVk);
2001                 break;
2002             case gl::Framebuffer::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
2003                 shouldUpdateSrgbWriteControlMode = true;
2004                 break;
2005             case gl::Framebuffer::DIRTY_BIT_DEFAULT_LAYERS:
2006                 shouldUpdateLayerCount = true;
2007                 break;
2008             default:
2009             {
2010                 static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
2011                 uint32_t colorIndexGL;
2012                 if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
2013                 {
2014                     colorIndexGL = static_cast<uint32_t>(
2015                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
2016                 }
2017                 else
2018                 {
2019                     ASSERT(dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 &&
2020                            dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX);
2021                     colorIndexGL = static_cast<uint32_t>(
2022                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
2023                 }
2024 
2025                 ANGLE_TRY(updateColorAttachment(context, colorIndexGL));
2026 
2027                 // Window system framebuffer only have one color attachment and its property should
2028                 // never change unless via DIRTY_BIT_DRAW_BUFFERS bit.
2029                 if (!mState.isDefault())
2030                 {
2031                     shouldUpdateColorMaskAndBlend = true;
2032                     shouldUpdateLayerCount        = true;
2033                 }
2034                 dirtyColorAttachments.set(colorIndexGL);
2035 
2036                 break;
2037             }
2038         }
2039     }
2040 
2041     if (shouldUpdateSrgbWriteControlMode)
2042     {
2043         // Framebuffer colorspace state has been modified, so refresh the current framebuffer
2044         // descriptor to reflect the new state.
2045         gl::SrgbWriteControlMode newSrgbWriteControlMode = mState.getWriteControlMode();
2046         mCurrentFramebufferDesc.setWriteControlMode(newSrgbWriteControlMode);
2047         mRenderPassDesc.setWriteControlMode(newSrgbWriteControlMode);
2048     }
2049 
2050     if (shouldUpdateColorMaskAndBlend)
2051     {
2052         contextVk->updateColorMasks();
2053         contextVk->updateBlendFuncsAndEquations();
2054     }
2055 
2056     if (shouldUpdateLayerCount)
2057     {
2058         updateLayerCount();
2059     }
2060 
2061     // Defer clears for draw framebuffer ops.  Note that this will result in a render area that
2062     // completely covers the framebuffer, even if the operation that follows is scissored.
2063     //
2064     // Additionally, defer clears for read framebuffer attachments that are not taking part in a
2065     // blit operation.
2066     const bool isBlitCommand = command >= gl::Command::Blit && command <= gl::Command::BlitAll;
2067 
2068     bool deferColorClears        = binding == GL_DRAW_FRAMEBUFFER;
2069     bool deferDepthStencilClears = binding == GL_DRAW_FRAMEBUFFER;
2070     if (binding == GL_READ_FRAMEBUFFER && isBlitCommand)
2071     {
2072         uint32_t blitMask =
2073             static_cast<uint32_t>(command) - static_cast<uint32_t>(gl::Command::Blit);
2074         if ((blitMask & gl::CommandBlitBufferColor) == 0)
2075         {
2076             deferColorClears = true;
2077         }
2078         if ((blitMask & (gl::CommandBlitBufferDepth | gl::CommandBlitBufferStencil)) == 0)
2079         {
2080             deferDepthStencilClears = true;
2081         }
2082     }
2083 
2084     // If we are notified that any attachment is dirty, but we have deferred clears for them, a
2085     // flushDeferredClears() call is missing somewhere.  ASSERT this to catch these bugs.
2086     vk::ClearValuesArray previousDeferredClears = mDeferredClears;
2087 
2088     for (size_t colorIndexGL : dirtyColorAttachments)
2089     {
2090         ASSERT(!previousDeferredClears.test(colorIndexGL));
2091         ANGLE_TRY(flushColorAttachmentUpdates(context, deferColorClears,
2092                                               static_cast<uint32_t>(colorIndexGL)));
2093     }
2094     if (dirtyDepthStencilAttachment)
2095     {
2096         ASSERT(!previousDeferredClears.testDepth());
2097         ASSERT(!previousDeferredClears.testStencil());
2098         ANGLE_TRY(flushDepthStencilAttachmentUpdates(context, deferDepthStencilClears));
2099     }
2100 
2101     // No-op redundant changes to prevent closing the RenderPass.
2102     if (mCurrentFramebufferDesc == priorFramebufferDesc &&
2103         mCurrentFramebufferDesc.attachmentCount() > 0)
2104     {
2105         return angle::Result::Continue;
2106     }
2107 
2108     if (!isBlitCommand)
2109     {
2110         // Don't end the render pass when handling a blit to resolve, since we may be able to
2111         // optimize that path which requires modifying the current render pass.
2112         // We're deferring the resolve check to FramebufferVk::blit(), since if the read buffer is
2113         // multisampled-render-to-texture, then srcFramebuffer->getSamples(context) gives > 1, but
2114         // there's no resolve happening as the read buffer's single sampled image will be used as
2115         // blit src. FramebufferVk::blit() will handle those details for us.
2116 
2117         // ContextVk::onFramebufferChange will end up calling onRenderPassFinished if necessary,
2118         // whih will trigger ending of current render pass if needed. But we still need to reset
2119         // mLastRenderPassQueueSerial so that it will not get reactivated, since the
2120         // mCurrentFramebufferDesc has changed.
2121         mLastRenderPassQueueSerial = QueueSerial();
2122     }
2123 
2124     updateRenderPassDesc(contextVk);
2125 
2126     // Deactivate Framebuffer
2127     releaseCurrentFramebuffer(contextVk);
2128 
2129     // Notify the ContextVk to update the pipeline desc.
2130     return contextVk->onFramebufferChange(this, command);
2131 }
2132 
updateRenderPassDesc(ContextVk * contextVk)2133 void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk)
2134 {
2135     mRenderPassDesc = {};
2136     mRenderPassDesc.setSamples(getSamples());
2137     mRenderPassDesc.setViewCount(
2138         mState.isMultiview() && mState.getNumViews() > 1 ? mState.getNumViews() : 0);
2139 
2140     // Color attachments.
2141     const auto &colorRenderTargets               = mRenderTargetCache.getColors();
2142     const gl::DrawBufferMask colorAttachmentMask = mState.getColorAttachmentsMask();
2143     for (size_t colorIndexGL = 0; colorIndexGL < colorAttachmentMask.size(); ++colorIndexGL)
2144     {
2145         if (colorAttachmentMask[colorIndexGL])
2146         {
2147             RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2148             ASSERT(colorRenderTarget);
2149             mRenderPassDesc.packColorAttachment(
2150                 colorIndexGL, colorRenderTarget->getImageForRenderPass().getActualFormatID());
2151 
2152             // Add the resolve attachment, if any.
2153             if (colorRenderTarget->hasResolveAttachment())
2154             {
2155                 mRenderPassDesc.packColorResolveAttachment(colorIndexGL);
2156             }
2157         }
2158         else
2159         {
2160             mRenderPassDesc.packColorAttachmentGap(colorIndexGL);
2161         }
2162     }
2163 
2164     // Depth/stencil attachment.
2165     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
2166     if (depthStencilRenderTarget)
2167     {
2168         mRenderPassDesc.packDepthStencilAttachment(
2169             depthStencilRenderTarget->getImageForRenderPass().getActualFormatID());
2170 
2171         // Add the resolve attachment, if any.
2172         if (depthStencilRenderTarget->hasResolveAttachment())
2173         {
2174             mRenderPassDesc.packDepthStencilResolveAttachment();
2175         }
2176     }
2177 
2178     if (contextVk->isInFramebufferFetchMode())
2179     {
2180         mRenderPassDesc.setFramebufferFetchMode(true);
2181     }
2182 
2183     if (contextVk->getFeatures().enableMultisampledRenderToTexture.enabled)
2184     {
2185         // Update descriptions regarding multisampled-render-to-texture use.
2186         bool isRenderToTexture = false;
2187         for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
2188         {
2189             const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
2190             ASSERT(color);
2191 
2192             if (color->isRenderToTexture())
2193             {
2194                 isRenderToTexture = true;
2195                 break;
2196             }
2197         }
2198         const gl::FramebufferAttachment *depthStencil = mState.getDepthStencilAttachment();
2199         if (depthStencil && depthStencil->isRenderToTexture())
2200         {
2201             isRenderToTexture = true;
2202         }
2203 
2204         mCurrentFramebufferDesc.updateRenderToTexture(isRenderToTexture);
2205         mRenderPassDesc.updateRenderToTexture(isRenderToTexture);
2206     }
2207 
2208     mCurrentFramebufferDesc.updateUnresolveMask({});
2209     mRenderPassDesc.setWriteControlMode(mCurrentFramebufferDesc.getWriteControlMode());
2210 
2211     updateLegacyDither(contextVk);
2212 }
2213 
getAttachmentsAndRenderTargets(ContextVk * contextVk,const vk::ImageView * resolveImageViewIn,RenderTargetVk * resolveRenderTargetIn,vk::FramebufferAttachmentsVector<VkImageView> * attachments,vk::FramebufferAttachmentsVector<RenderTargetInfo> * renderTargetsInfoOut)2214 angle::Result FramebufferVk::getAttachmentsAndRenderTargets(
2215     ContextVk *contextVk,
2216     const vk::ImageView *resolveImageViewIn,
2217     RenderTargetVk *resolveRenderTargetIn,
2218     vk::FramebufferAttachmentsVector<VkImageView> *attachments,
2219     vk::FramebufferAttachmentsVector<RenderTargetInfo> *renderTargetsInfoOut)
2220 {
2221     // Color attachments.
2222     const auto &colorRenderTargets = mRenderTargetCache.getColors();
2223     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2224     {
2225         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2226         ASSERT(colorRenderTarget);
2227 
2228         const vk::ImageView *imageView = nullptr;
2229         ANGLE_TRY(colorRenderTarget->getImageViewWithColorspace(
2230             contextVk, mCurrentFramebufferDesc.getWriteControlMode(), &imageView));
2231 
2232         attachments->push_back(imageView->getHandle());
2233         renderTargetsInfoOut->emplace_back(
2234             RenderTargetInfo(colorRenderTarget, RenderTargetImage::AttachmentImage));
2235     }
2236 
2237     // Depth/stencil attachment.
2238     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
2239     if (depthStencilRenderTarget)
2240     {
2241         const vk::ImageView *imageView = nullptr;
2242         ANGLE_TRY(depthStencilRenderTarget->getImageView(contextVk, &imageView));
2243 
2244         attachments->push_back(imageView->getHandle());
2245         renderTargetsInfoOut->emplace_back(
2246             RenderTargetInfo(depthStencilRenderTarget, RenderTargetImage::AttachmentImage));
2247     }
2248 
2249     // Color resolve attachments.
2250     if (resolveImageViewIn)
2251     {
2252         ASSERT(!HasResolveAttachment(colorRenderTargets, mState.getEnabledDrawBuffers()));
2253         ASSERT(resolveRenderTargetIn);
2254 
2255         // Need to use the passed in ImageView for the resolve attachment, since it came from
2256         // another Framebuffer.
2257         attachments->push_back(resolveImageViewIn->getHandle());
2258         renderTargetsInfoOut->emplace_back(
2259             RenderTargetInfo(resolveRenderTargetIn, (resolveRenderTargetIn->hasResolveAttachment())
2260                                                         ? RenderTargetImage::ResolveImage
2261                                                         : RenderTargetImage::AttachmentImage));
2262     }
2263     else
2264     {
2265         // This Framebuffer owns all of the ImageViews, including its own resolve ImageViews.
2266         for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2267         {
2268             RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2269             ASSERT(colorRenderTarget);
2270 
2271             if (colorRenderTarget->hasResolveAttachment())
2272             {
2273                 const vk::ImageView *resolveImageView = nullptr;
2274                 ANGLE_TRY(colorRenderTarget->getResolveImageView(contextVk, &resolveImageView));
2275 
2276                 attachments->push_back(resolveImageView->getHandle());
2277                 renderTargetsInfoOut->emplace_back(
2278                     RenderTargetInfo(colorRenderTarget, RenderTargetImage::ResolveImage));
2279             }
2280         }
2281     }
2282 
2283     // Depth/stencil resolve attachment.
2284     if (depthStencilRenderTarget && depthStencilRenderTarget->hasResolveAttachment())
2285     {
2286         const vk::ImageView *imageView = nullptr;
2287         ANGLE_TRY(depthStencilRenderTarget->getResolveImageView(contextVk, &imageView));
2288 
2289         attachments->push_back(imageView->getHandle());
2290         renderTargetsInfoOut->emplace_back(
2291             RenderTargetInfo(depthStencilRenderTarget, RenderTargetImage::ResolveImage));
2292     }
2293 
2294     return angle::Result::Continue;
2295 }
2296 
getFramebuffer(ContextVk * contextVk,vk::MaybeImagelessFramebuffer * framebufferOut,RenderTargetVk * resolveRenderTargetIn,const vk::ImageView * resolveImageViewIn,const SwapchainResolveMode swapchainResolveMode)2297 angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
2298                                             vk::MaybeImagelessFramebuffer *framebufferOut,
2299                                             RenderTargetVk *resolveRenderTargetIn,
2300                                             const vk::ImageView *resolveImageViewIn,
2301                                             const SwapchainResolveMode swapchainResolveMode)
2302 {
2303     ASSERT(mCurrentFramebufferDesc.hasFramebufferFetch() == mRenderPassDesc.hasFramebufferFetch());
2304 
2305     // When using imageless framebuffers, the framebuffer cache is not utilized.
2306     bool useImagelessFramebuffer =
2307         contextVk->getFeatures().supportsImagelessFramebuffer.enabled && mBackbuffer == nullptr;
2308     vk::ImagelessStatus useImagelessFramebufferStatus = (useImagelessFramebuffer)
2309                                                             ? vk::ImagelessStatus::Imageless
2310                                                             : vk::ImagelessStatus::NotImageless;
2311 
2312     // First return a presently valid Framebuffer
2313     if (mCurrentFramebuffer.valid())
2314     {
2315         // With imageless framebuffers, the image views used for the beginning of the render pass
2316         // should be updated.
2317         if (useImagelessFramebuffer)
2318         {
2319             vk::FramebufferAttachmentsVector<VkImageView> attachments;
2320             vk::FramebufferAttachmentsVector<RenderTargetInfo> renderTargetsInfo;
2321             ANGLE_TRY(getAttachmentsAndRenderTargets(contextVk, resolveImageViewIn,
2322                                                      resolveRenderTargetIn, &attachments,
2323                                                      &renderTargetsInfo));
2324             framebufferOut->updateFramebuffer(mCurrentFramebuffer.getHandle(), &attachments,
2325                                               useImagelessFramebufferStatus);
2326         }
2327 
2328         framebufferOut->setHandle(mCurrentFramebuffer.getHandle());
2329         return angle::Result::Continue;
2330     }
2331 
2332     // No current FB, so now check for previously cached Framebuffer.
2333     if (mBackbuffer == nullptr && !useImagelessFramebuffer &&
2334         contextVk->getShareGroup()->getFramebufferCache().get(contextVk, mCurrentFramebufferDesc,
2335                                                               mCurrentFramebuffer))
2336     {
2337         ASSERT(mCurrentFramebuffer.valid());
2338         mIsCurrentFramebufferCached = true;
2339         framebufferOut->setHandle(mCurrentFramebuffer.getHandle());
2340         return angle::Result::Continue;
2341     }
2342 
2343     const vk::RenderPass *compatibleRenderPass = nullptr;
2344     ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));
2345 
2346     // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
2347     if (mBackbuffer)
2348     {
2349         return mBackbuffer->getCurrentFramebuffer(
2350             contextVk,
2351             mRenderPassDesc.hasFramebufferFetch() ? FramebufferFetchMode::Enabled
2352                                                   : FramebufferFetchMode::Disabled,
2353             *compatibleRenderPass, swapchainResolveMode, framebufferOut);
2354     }
2355 
2356     // Gather VkImageViews over all FBO attachments, also size of attached region.
2357     vk::FramebufferAttachmentsVector<VkImageView> attachments;
2358     vk::FramebufferAttachmentsVector<RenderTargetInfo> renderTargetsInfo;
2359     gl::Extents attachmentsSize = mState.getExtents();
2360     ASSERT(attachmentsSize.width != 0 && attachmentsSize.height != 0);
2361     ANGLE_TRY(getAttachmentsAndRenderTargets(contextVk, resolveImageViewIn, resolveRenderTargetIn,
2362                                              &attachments, &renderTargetsInfo));
2363 
2364     // Create new framebuffer.
2365     vk::FramebufferHelper newFramebuffer;
2366 
2367     VkFramebufferCreateInfo framebufferInfo = {};
2368     framebufferInfo.sType                   = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2369     framebufferInfo.flags                   = 0;
2370     framebufferInfo.renderPass              = compatibleRenderPass->getHandle();
2371     framebufferInfo.attachmentCount         = static_cast<uint32_t>(attachments.size());
2372     framebufferInfo.pAttachments            = attachments.data();
2373     framebufferInfo.width                   = static_cast<uint32_t>(attachmentsSize.width);
2374     framebufferInfo.height                  = static_cast<uint32_t>(attachmentsSize.height);
2375     framebufferInfo.layers                  = (!mCurrentFramebufferDesc.isMultiview())
2376                                                   ? std::max(mCurrentFramebufferDesc.getLayerCount(), 1u)
2377                                                   : 1;
2378 
2379     // Check that our description matches our attachments. Can catch implementation bugs.
2380     ASSERT(static_cast<uint32_t>(attachments.size()) == mCurrentFramebufferDesc.attachmentCount());
2381 
2382     if (!useImagelessFramebuffer)
2383     {
2384         // Since the cache key FramebufferDesc can't distinguish between
2385         // two FramebufferHelper, if they both have 0 attachment, but their sizes
2386         // are different, we could have wrong cache hit(new framebufferHelper has
2387         // a bigger height and width, but get cache hit with framebufferHelper of
2388         // lower height and width). As a workaround, do not cache the
2389         // FramebufferHelper if it doesn't have any attachment.
2390         ANGLE_TRY(newFramebuffer.init(contextVk, framebufferInfo));
2391         if (!attachments.empty())
2392         {
2393             insertCache(contextVk, mCurrentFramebufferDesc, std::move(newFramebuffer));
2394 
2395             bool result = contextVk->getShareGroup()->getFramebufferCache().get(
2396                 contextVk, mCurrentFramebufferDesc, mCurrentFramebuffer);
2397             ASSERT(result);
2398             mIsCurrentFramebufferCached = true;
2399         }
2400         else
2401         {
2402             mCurrentFramebuffer         = std::move(newFramebuffer.getFramebuffer());
2403             mIsCurrentFramebufferCached = false;
2404         }
2405     }
2406     else
2407     {
2408         // For imageless framebuffers, attachment image and create info objects should be defined
2409         // when creating the new framebuffer.
2410         std::vector<VkFramebufferAttachmentImageInfoKHR> fbAttachmentImageInfoArray;
2411 
2412         for (auto const &info : renderTargetsInfo)
2413         {
2414             vk::ImageHelper *renderTargetImage =
2415                 (info.renderTargetImage == RenderTargetImage::ResolveImage)
2416                     ? &info.renderTarget->getResolveImageForRenderPass()
2417                     : &info.renderTarget->getImageForRenderPass();
2418             uint32_t renderTargetLevel      = info.renderTarget->getLevelIndex().get();
2419             uint32_t renderTargetLayerCount = info.renderTarget->getLayerCount();
2420 
2421             VkFramebufferAttachmentImageInfoKHR fbAttachmentImageInfo = {};
2422             fbAttachmentImageInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR;
2423 
2424             uint32_t baseLevel =
2425                 static_cast<uint32_t>(renderTargetImage->getFirstAllocatedLevel().get());
2426             uint32_t level = (renderTargetLevel > baseLevel) ? (renderTargetLevel - baseLevel) : 0;
2427             uint32_t fbAttachmentWidth   = renderTargetImage->getExtents().width >> level;
2428             uint32_t fbAttachmentHeight  = renderTargetImage->getExtents().height >> level;
2429             fbAttachmentImageInfo.width  = (fbAttachmentWidth > 0) ? fbAttachmentWidth : 1;
2430             fbAttachmentImageInfo.height = (fbAttachmentHeight > 0) ? fbAttachmentHeight : 1;
2431 
2432             fbAttachmentImageInfo.layerCount =
2433                 (mCurrentFramebufferDesc.isMultiview())
2434                     ? std::max(static_cast<uint32_t>(mRenderPassDesc.viewCount()), 1u)
2435                     : renderTargetLayerCount;
2436             fbAttachmentImageInfo.flags = renderTargetImage->getCreateFlags();
2437             fbAttachmentImageInfo.usage = renderTargetImage->getUsage();
2438             fbAttachmentImageInfo.viewFormatCount =
2439                 static_cast<uint32_t>(renderTargetImage->getViewFormats().max_size());
2440             fbAttachmentImageInfo.pViewFormats = renderTargetImage->getViewFormats().data();
2441 
2442             fbAttachmentImageInfoArray.push_back(fbAttachmentImageInfo);
2443         }
2444 
2445         VkFramebufferAttachmentsCreateInfoKHR fbAttachmentsCreateInfo = {};
2446         fbAttachmentsCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR;
2447         fbAttachmentsCreateInfo.attachmentImageInfoCount =
2448             static_cast<uint32_t>(fbAttachmentImageInfoArray.size());
2449         fbAttachmentsCreateInfo.pAttachmentImageInfos = fbAttachmentImageInfoArray.data();
2450 
2451         framebufferInfo.flags |= VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR;
2452         framebufferInfo.pAttachments = nullptr;
2453         vk::AddToPNextChain(&framebufferInfo, &fbAttachmentsCreateInfo);
2454 
2455         ANGLE_TRY(newFramebuffer.init(contextVk, framebufferInfo));
2456         mCurrentFramebuffer.setHandle(newFramebuffer.getFramebuffer().release());
2457 
2458         // Update the image views to be used to begin the render pass.
2459         framebufferOut->updateFramebuffer(mCurrentFramebuffer.getHandle(), &attachments,
2460                                           useImagelessFramebufferStatus);
2461     }
2462 
2463     ASSERT(mCurrentFramebuffer.valid());
2464 
2465     framebufferOut->setHandle(mCurrentFramebuffer.getHandle());
2466     return angle::Result::Continue;
2467 }
2468 
mergeClearsWithDeferredClears(gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)2469 void FramebufferVk::mergeClearsWithDeferredClears(
2470     gl::DrawBufferMask clearColorBuffers,
2471     bool clearDepth,
2472     bool clearStencil,
2473     const VkClearColorValue &clearColorValue,
2474     const VkClearDepthStencilValue &clearDepthStencilValue)
2475 {
2476     // Apply clears to mDeferredClears.  Note that clears override deferred clears.
2477 
2478     // Color clears.
2479     for (size_t colorIndexGL : clearColorBuffers)
2480     {
2481         ASSERT(mState.getEnabledDrawBuffers().test(colorIndexGL));
2482         VkClearValue clearValue = getCorrectedColorClearValue(colorIndexGL, clearColorValue);
2483         mDeferredClears.store(static_cast<uint32_t>(colorIndexGL), VK_IMAGE_ASPECT_COLOR_BIT,
2484                               clearValue);
2485     }
2486 
2487     // Depth and stencil clears.
2488     VkImageAspectFlags dsAspectFlags = 0;
2489     VkClearValue dsClearValue        = {};
2490     dsClearValue.depthStencil        = clearDepthStencilValue;
2491     if (clearDepth)
2492     {
2493         dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2494     }
2495     if (clearStencil)
2496     {
2497         dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2498     }
2499 
2500     if (dsAspectFlags != 0)
2501     {
2502         mDeferredClears.store(vk::kUnpackedDepthIndex, dsAspectFlags, dsClearValue);
2503     }
2504 }
2505 
clearWithDraw(ContextVk * contextVk,const gl::Rectangle & clearArea,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,gl::BlendStateExt::ColorMaskStorage::Type colorMasks,uint8_t stencilMask,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)2506 angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
2507                                            const gl::Rectangle &clearArea,
2508                                            gl::DrawBufferMask clearColorBuffers,
2509                                            bool clearDepth,
2510                                            bool clearStencil,
2511                                            gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
2512                                            uint8_t stencilMask,
2513                                            const VkClearColorValue &clearColorValue,
2514                                            const VkClearDepthStencilValue &clearDepthStencilValue)
2515 {
2516     // All deferred clears should be handled already.
2517     ASSERT(mDeferredClears.empty());
2518 
2519     UtilsVk::ClearFramebufferParameters params = {};
2520     params.clearArea                           = clearArea;
2521     params.colorClearValue                     = clearColorValue;
2522     params.depthStencilClearValue              = clearDepthStencilValue;
2523     params.stencilMask                         = stencilMask;
2524 
2525     params.clearColor   = true;
2526     params.clearDepth   = clearDepth;
2527     params.clearStencil = clearStencil;
2528 
2529     const auto &colorRenderTargets = mRenderTargetCache.getColors();
2530     for (size_t colorIndexGL : clearColorBuffers)
2531     {
2532         const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2533         ASSERT(colorRenderTarget);
2534 
2535         params.colorFormat = &colorRenderTarget->getImageForRenderPass().getActualFormat();
2536         params.colorAttachmentIndexGL = static_cast<uint32_t>(colorIndexGL);
2537         params.colorMaskFlags =
2538             gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(colorIndexGL, colorMasks);
2539         if (mEmulatedAlphaAttachmentMask[colorIndexGL])
2540         {
2541             params.colorMaskFlags &= ~VK_COLOR_COMPONENT_A_BIT;
2542         }
2543 
2544         // TODO: implement clear of layered framebuffers.  UtilsVk::clearFramebuffer should add a
2545         // geometry shader that is instanced layerCount times (or loops layerCount times), each time
2546         // selecting a different layer.
2547         // http://anglebug.com/5453
2548         ASSERT(mCurrentFramebufferDesc.isMultiview() || colorRenderTarget->getLayerCount() == 1);
2549 
2550         ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
2551 
2552         // Clear depth/stencil only once!
2553         params.clearDepth   = false;
2554         params.clearStencil = false;
2555     }
2556 
2557     // If there was no color clear, clear depth/stencil alone.
2558     if (params.clearDepth || params.clearStencil)
2559     {
2560         params.clearColor = false;
2561         ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
2562     }
2563 
2564     return angle::Result::Continue;
2565 }
2566 
getCorrectedColorClearValue(size_t colorIndexGL,const VkClearColorValue & clearColor) const2567 VkClearValue FramebufferVk::getCorrectedColorClearValue(size_t colorIndexGL,
2568                                                         const VkClearColorValue &clearColor) const
2569 {
2570     VkClearValue clearValue = {};
2571     clearValue.color        = clearColor;
2572 
2573     if (!mEmulatedAlphaAttachmentMask[colorIndexGL])
2574     {
2575         return clearValue;
2576     }
2577 
2578     // If the render target doesn't have alpha, but its emulated format has it, clear the alpha
2579     // to 1.
2580     RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
2581     const angle::Format &format  = renderTarget->getImageActualFormat();
2582 
2583     if (format.isUint())
2584     {
2585         clearValue.color.uint32[3] = kEmulatedAlphaValue;
2586     }
2587     else if (format.isSint())
2588     {
2589         clearValue.color.int32[3] = kEmulatedAlphaValue;
2590     }
2591     else
2592     {
2593         clearValue.color.float32[3] = kEmulatedAlphaValue;
2594     }
2595 
2596     return clearValue;
2597 }
2598 
redeferClears(ContextVk * contextVk)2599 void FramebufferVk::redeferClears(ContextVk *contextVk)
2600 {
2601     // Called when redeferring clears of the draw framebuffer.  In that case, there can't be any
2602     // render passes open, otherwise the clear would have applied to the render pass.  In the
2603     // exceptional occasion in blit where the read framebuffer accumulates deferred clears, it can
2604     // be deferred while this assumption doesn't hold (and redeferClearsForReadFramebuffer should be
2605     // used instead).
2606     ASSERT(!contextVk->hasActiveRenderPass() || !mDeferredClears.any());
2607     redeferClearsImpl(contextVk);
2608 }
2609 
redeferClearsForReadFramebuffer(ContextVk * contextVk)2610 void FramebufferVk::redeferClearsForReadFramebuffer(ContextVk *contextVk)
2611 {
2612     redeferClearsImpl(contextVk);
2613 }
2614 
redeferClearsImpl(ContextVk * contextVk)2615 void FramebufferVk::redeferClearsImpl(ContextVk *contextVk)
2616 {
2617     // Set the appropriate aspect and clear values for depth and stencil.
2618     VkImageAspectFlags dsAspectFlags  = 0;
2619     VkClearValue dsClearValue         = {};
2620     dsClearValue.depthStencil.depth   = mDeferredClears.getDepthValue();
2621     dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
2622 
2623     if (mDeferredClears.testDepth())
2624     {
2625         dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2626         mDeferredClears.reset(vk::kUnpackedDepthIndex);
2627     }
2628 
2629     if (mDeferredClears.testStencil())
2630     {
2631         dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2632         mDeferredClears.reset(vk::kUnpackedStencilIndex);
2633     }
2634 
2635     // Go through deferred clears and stage the clears for future.
2636     for (size_t colorIndexGL : mDeferredClears.getColorMask())
2637     {
2638         RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
2639         gl::ImageIndex imageIndex =
2640             renderTarget->getImageIndexForClear(mCurrentFramebufferDesc.getLayerCount());
2641         renderTarget->getImageForWrite().stageClear(imageIndex, VK_IMAGE_ASPECT_COLOR_BIT,
2642                                                     mDeferredClears[colorIndexGL]);
2643         mDeferredClears.reset(colorIndexGL);
2644     }
2645 
2646     if (dsAspectFlags)
2647     {
2648         RenderTargetVk *renderTarget = getDepthStencilRenderTarget();
2649         ASSERT(renderTarget);
2650 
2651         gl::ImageIndex imageIndex =
2652             renderTarget->getImageIndexForClear(mCurrentFramebufferDesc.getLayerCount());
2653         renderTarget->getImageForWrite().stageClear(imageIndex, dsAspectFlags, dsClearValue);
2654     }
2655 }
2656 
clearWithCommand(ContextVk * contextVk,const gl::Rectangle & scissoredRenderArea,ClearWithCommand behavior,vk::ClearValuesArray * clears)2657 void FramebufferVk::clearWithCommand(ContextVk *contextVk,
2658                                      const gl::Rectangle &scissoredRenderArea,
2659                                      ClearWithCommand behavior,
2660                                      vk::ClearValuesArray *clears)
2661 {
2662     // Clear is not affected by viewport, so ContextVk::updateScissor may have decided on a smaller
2663     // render area.  Grow the render area to the full framebuffer size as this clear path is taken
2664     // when not scissored.
2665     vk::RenderPassCommandBufferHelper *renderPassCommands =
2666         &contextVk->getStartedRenderPassCommands();
2667     renderPassCommands->growRenderArea(contextVk, scissoredRenderArea);
2668 
2669     gl::AttachmentVector<VkClearAttachment> attachments;
2670 
2671     const bool optimizeWithLoadOp = behavior == ClearWithCommand::OptimizeWithLoadOp;
2672 
2673     // Go through deferred clears and add them to the list of attachments to clear.  If any
2674     // attachment is unused, skip the clear.  clearWithLoadOp will follow and move the remaining
2675     // clears up to loadOp.
2676     vk::PackedAttachmentIndex colorIndexVk(0);
2677     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2678     {
2679         if (clears->getColorMask().test(colorIndexGL))
2680         {
2681             if (!renderPassCommands->hasAnyColorAccess(colorIndexVk) && optimizeWithLoadOp)
2682             {
2683                 // Skip this attachment, so we can use a renderpass loadOp to clear it instead.
2684                 // Note that if loadOp=Clear was already used for this color attachment, it will be
2685                 // overriden by the new clear, which is valid because the attachment wasn't used in
2686                 // between.
2687                 ++colorIndexVk;
2688                 continue;
2689             }
2690 
2691             attachments.emplace_back(VkClearAttachment{VK_IMAGE_ASPECT_COLOR_BIT,
2692                                                        static_cast<uint32_t>(colorIndexGL),
2693                                                        (*clears)[colorIndexGL]});
2694             clears->reset(colorIndexGL);
2695             ++contextVk->getPerfCounters().colorClearAttachments;
2696 
2697             renderPassCommands->onColorAccess(colorIndexVk, vk::ResourceAccess::ReadWrite);
2698         }
2699         ++colorIndexVk;
2700     }
2701 
2702     // Add depth and stencil to list of attachments as needed.
2703     VkImageAspectFlags dsAspectFlags  = 0;
2704     VkClearValue dsClearValue         = {};
2705     dsClearValue.depthStencil.depth   = clears->getDepthValue();
2706     dsClearValue.depthStencil.stencil = clears->getStencilValue();
2707     if (clears->testDepth() && (renderPassCommands->hasAnyDepthAccess() || !optimizeWithLoadOp))
2708     {
2709         dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2710         // Explicitly mark a depth write because we are clearing the depth buffer.
2711         renderPassCommands->onDepthAccess(vk::ResourceAccess::ReadWrite);
2712         clears->reset(vk::kUnpackedDepthIndex);
2713         ++contextVk->getPerfCounters().depthClearAttachments;
2714     }
2715 
2716     if (clears->testStencil() && (renderPassCommands->hasAnyStencilAccess() || !optimizeWithLoadOp))
2717     {
2718         dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2719         // Explicitly mark a stencil write because we are clearing the stencil buffer.
2720         renderPassCommands->onStencilAccess(vk::ResourceAccess::ReadWrite);
2721         clears->reset(vk::kUnpackedStencilIndex);
2722         ++contextVk->getPerfCounters().stencilClearAttachments;
2723     }
2724 
2725     if (dsAspectFlags != 0)
2726     {
2727         attachments.emplace_back(VkClearAttachment{dsAspectFlags, 0, dsClearValue});
2728 
2729         // Because we may have changed the depth/stencil access mode, update read only depth/stencil
2730         // mode.
2731         renderPassCommands->updateDepthStencilReadOnlyMode(
2732             contextVk->getDepthStencilAttachmentFlags(), dsAspectFlags);
2733     }
2734 
2735     if (attachments.empty())
2736     {
2737         // If called with the intent to definitely clear something with vkCmdClearAttachments, there
2738         // must have been something to clear!
2739         ASSERT(optimizeWithLoadOp);
2740         return;
2741     }
2742 
2743     const uint32_t layerCount = mState.isMultiview() ? 1 : mCurrentFramebufferDesc.getLayerCount();
2744 
2745     VkClearRect rect                                     = {};
2746     rect.rect.offset.x                                   = scissoredRenderArea.x;
2747     rect.rect.offset.y                                   = scissoredRenderArea.y;
2748     rect.rect.extent.width                               = scissoredRenderArea.width;
2749     rect.rect.extent.height                              = scissoredRenderArea.height;
2750     rect.layerCount                                      = layerCount;
2751     vk::RenderPassCommandBuffer *renderPassCommandBuffer = &renderPassCommands->getCommandBuffer();
2752 
2753     renderPassCommandBuffer->clearAttachments(static_cast<uint32_t>(attachments.size()),
2754                                               attachments.data(), 1, &rect);
2755     return;
2756 }
2757 
clearWithLoadOp(ContextVk * contextVk)2758 void FramebufferVk::clearWithLoadOp(ContextVk *contextVk)
2759 {
2760     vk::RenderPassCommandBufferHelper *renderPassCommands =
2761         &contextVk->getStartedRenderPassCommands();
2762 
2763     // Update the render pass loadOps to clear the attachments.
2764     vk::PackedAttachmentIndex colorIndexVk(0);
2765     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2766     {
2767         if (!mDeferredClears.test(colorIndexGL))
2768         {
2769             ++colorIndexVk;
2770             continue;
2771         }
2772 
2773         ASSERT(!renderPassCommands->hasAnyColorAccess(colorIndexVk));
2774 
2775         renderPassCommands->updateRenderPassColorClear(colorIndexVk, mDeferredClears[colorIndexGL]);
2776 
2777         mDeferredClears.reset(colorIndexGL);
2778 
2779         ++colorIndexVk;
2780     }
2781 
2782     VkClearValue dsClearValue         = {};
2783     dsClearValue.depthStencil.depth   = mDeferredClears.getDepthValue();
2784     dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
2785     VkImageAspectFlags dsAspects      = 0;
2786 
2787     if (mDeferredClears.testDepth())
2788     {
2789         ASSERT(!renderPassCommands->hasAnyDepthAccess());
2790         dsAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
2791         mDeferredClears.reset(vk::kUnpackedDepthIndex);
2792     }
2793 
2794     if (mDeferredClears.testStencil())
2795     {
2796         ASSERT(!renderPassCommands->hasAnyStencilAccess());
2797         dsAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
2798         mDeferredClears.reset(vk::kUnpackedStencilIndex);
2799     }
2800 
2801     if (dsAspects != 0)
2802     {
2803         renderPassCommands->updateRenderPassDepthStencilClear(dsAspects, dsClearValue);
2804 
2805         // The render pass can no longer be in read-only depth/stencil mode.
2806         renderPassCommands->updateDepthStencilReadOnlyMode(
2807             contextVk->getDepthStencilAttachmentFlags(), dsAspects);
2808     }
2809 }
2810 
getSamplePosition(const gl::Context * context,size_t index,GLfloat * xy) const2811 angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
2812                                                size_t index,
2813                                                GLfloat *xy) const
2814 {
2815     int sampleCount = getSamples();
2816     rx::GetSamplePosition(sampleCount, index, xy);
2817     return angle::Result::Continue;
2818 }
2819 
startNewRenderPass(ContextVk * contextVk,const gl::Rectangle & renderArea,vk::RenderPassCommandBuffer ** commandBufferOut,bool * renderPassDescChangedOut)2820 angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
2821                                                 const gl::Rectangle &renderArea,
2822                                                 vk::RenderPassCommandBuffer **commandBufferOut,
2823                                                 bool *renderPassDescChangedOut)
2824 {
2825     ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
2826 
2827     // Initialize RenderPass info.
2828     vk::AttachmentOpsArray renderPassAttachmentOps;
2829     vk::PackedClearValuesArray packedClearValues;
2830     gl::DrawBufferMask previousUnresolveColorMask =
2831         mRenderPassDesc.getColorUnresolveAttachmentMask();
2832     const bool hasDeferredClears        = mDeferredClears.any();
2833     const bool previousUnresolveDepth   = mRenderPassDesc.hasDepthUnresolveAttachment();
2834     const bool previousUnresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();
2835 
2836     // Make sure render pass and framebuffer are in agreement w.r.t unresolve attachments.
2837     ASSERT(mCurrentFramebufferDesc.getUnresolveAttachmentMask() ==
2838            MakeUnresolveAttachmentMask(mRenderPassDesc));
2839 
2840     // Color attachments.
2841     const auto &colorRenderTargets = mRenderTargetCache.getColors();
2842     vk::PackedAttachmentIndex colorIndexVk(0);
2843     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
2844     {
2845         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
2846         ASSERT(colorRenderTarget);
2847 
2848         // Color render targets are never entirely transient.  Only depth/stencil
2849         // multisampled-render-to-texture textures can be so.
2850         ASSERT(!colorRenderTarget->isEntirelyTransient());
2851         const vk::RenderPassStoreOp storeOp = colorRenderTarget->isImageTransient()
2852                                                   ? vk::RenderPassStoreOp::DontCare
2853                                                   : vk::RenderPassStoreOp::Store;
2854 
2855         if (mDeferredClears.test(colorIndexGL))
2856         {
2857             renderPassAttachmentOps.setOps(colorIndexVk, vk::RenderPassLoadOp::Clear, storeOp);
2858             packedClearValues.store(colorIndexVk, VK_IMAGE_ASPECT_COLOR_BIT,
2859                                     mDeferredClears[colorIndexGL]);
2860             mDeferredClears.reset(colorIndexGL);
2861         }
2862         else
2863         {
2864             const vk::RenderPassLoadOp loadOp = colorRenderTarget->hasDefinedContent()
2865                                                     ? vk::RenderPassLoadOp::Load
2866                                                     : vk::RenderPassLoadOp::DontCare;
2867 
2868             renderPassAttachmentOps.setOps(colorIndexVk, loadOp, storeOp);
2869             packedClearValues.store(colorIndexVk, VK_IMAGE_ASPECT_COLOR_BIT,
2870                                     kUninitializedClearValue);
2871         }
2872         renderPassAttachmentOps.setStencilOps(colorIndexVk, vk::RenderPassLoadOp::DontCare,
2873                                               vk::RenderPassStoreOp::DontCare);
2874 
2875         // If there's a resolve attachment, and loadOp needs to be LOAD, the multisampled attachment
2876         // needs to take its value from the resolve attachment.  In this case, an initial subpass is
2877         // added for this very purpose which uses the resolve attachment as input attachment.  As a
2878         // result, loadOp of the multisampled attachment can remain DONT_CARE.
2879         //
2880         // Note that this only needs to be done if the multisampled image and the resolve attachment
2881         // come from the same source.  isImageTransient() indicates whether this should happen.
2882         if (colorRenderTarget->hasResolveAttachment() && colorRenderTarget->isImageTransient())
2883         {
2884             if (renderPassAttachmentOps[colorIndexVk].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
2885             {
2886                 renderPassAttachmentOps[colorIndexVk].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
2887 
2888                 // Update the render pass desc to specify that this attachment should be unresolved.
2889                 mRenderPassDesc.packColorUnresolveAttachment(colorIndexGL);
2890             }
2891             else
2892             {
2893                 mRenderPassDesc.removeColorUnresolveAttachment(colorIndexGL);
2894             }
2895         }
2896         else
2897         {
2898             ASSERT(!mRenderPassDesc.getColorUnresolveAttachmentMask().test(colorIndexGL));
2899         }
2900 
2901         ++colorIndexVk;
2902     }
2903 
2904     // Depth/stencil attachment.
2905     vk::PackedAttachmentIndex depthStencilAttachmentIndex = vk::kAttachmentIndexInvalid;
2906     RenderTargetVk *depthStencilRenderTarget              = getDepthStencilRenderTarget();
2907     if (depthStencilRenderTarget)
2908     {
2909         // depth stencil attachment always immediately follows color attachment
2910         depthStencilAttachmentIndex = colorIndexVk;
2911 
2912         vk::RenderPassLoadOp depthLoadOp     = vk::RenderPassLoadOp::Load;
2913         vk::RenderPassLoadOp stencilLoadOp   = vk::RenderPassLoadOp::Load;
2914         vk::RenderPassStoreOp depthStoreOp   = vk::RenderPassStoreOp::Store;
2915         vk::RenderPassStoreOp stencilStoreOp = vk::RenderPassStoreOp::Store;
2916 
2917         // If the image data was previously discarded (with no update in between), don't attempt to
2918         // load the image.  Additionally, if the multisampled image data is transient and there is
2919         // no resolve attachment, there's no data to load.  The latter is the case with
2920         // depth/stencil texture attachments per GL_EXT_multisampled_render_to_texture2.
2921         if (!depthStencilRenderTarget->hasDefinedContent() ||
2922             depthStencilRenderTarget->isEntirelyTransient())
2923         {
2924             depthLoadOp = vk::RenderPassLoadOp::DontCare;
2925         }
2926         if (!depthStencilRenderTarget->hasDefinedStencilContent() ||
2927             depthStencilRenderTarget->isEntirelyTransient())
2928         {
2929             stencilLoadOp = vk::RenderPassLoadOp::DontCare;
2930         }
2931 
2932         // If depth/stencil image is transient, no need to store its data at the end of the render
2933         // pass.
2934         if (depthStencilRenderTarget->isImageTransient())
2935         {
2936             depthStoreOp   = vk::RenderPassStoreOp::DontCare;
2937             stencilStoreOp = vk::RenderPassStoreOp::DontCare;
2938         }
2939 
2940         if (mDeferredClears.testDepth() || mDeferredClears.testStencil())
2941         {
2942             VkClearValue clearValue = {};
2943 
2944             if (mDeferredClears.testDepth())
2945             {
2946                 depthLoadOp                   = vk::RenderPassLoadOp::Clear;
2947                 clearValue.depthStencil.depth = mDeferredClears.getDepthValue();
2948                 mDeferredClears.reset(vk::kUnpackedDepthIndex);
2949             }
2950 
2951             if (mDeferredClears.testStencil())
2952             {
2953                 stencilLoadOp                   = vk::RenderPassLoadOp::Clear;
2954                 clearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
2955                 mDeferredClears.reset(vk::kUnpackedStencilIndex);
2956             }
2957 
2958             // Note the aspect is only depth here. That's intentional.
2959             packedClearValues.store(depthStencilAttachmentIndex, VK_IMAGE_ASPECT_DEPTH_BIT,
2960                                     clearValue);
2961         }
2962         else
2963         {
2964             // Note the aspect is only depth here. That's intentional.
2965             packedClearValues.store(depthStencilAttachmentIndex, VK_IMAGE_ASPECT_DEPTH_BIT,
2966                                     kUninitializedClearValue);
2967         }
2968 
2969         const angle::Format &format = depthStencilRenderTarget->getImageIntendedFormat();
2970         // If the format we picked has stencil but user did not ask for it due to hardware
2971         // limitations, use DONT_CARE for load/store. The same logic for depth follows.
2972         if (format.stencilBits == 0)
2973         {
2974             stencilLoadOp  = vk::RenderPassLoadOp::DontCare;
2975             stencilStoreOp = vk::RenderPassStoreOp::DontCare;
2976         }
2977         if (format.depthBits == 0)
2978         {
2979             depthLoadOp  = vk::RenderPassLoadOp::DontCare;
2980             depthStoreOp = vk::RenderPassStoreOp::DontCare;
2981         }
2982 
2983         // Similar to color attachments, if there's a resolve attachment and the multisampled image
2984         // is transient, depth/stencil data need to be unresolved in an initial subpass.
2985         if (depthStencilRenderTarget->hasResolveAttachment() &&
2986             depthStencilRenderTarget->isImageTransient())
2987         {
2988             const bool unresolveDepth   = depthLoadOp == vk::RenderPassLoadOp::Load;
2989             const bool unresolveStencil = stencilLoadOp == vk::RenderPassLoadOp::Load;
2990 
2991             if (unresolveDepth)
2992             {
2993                 depthLoadOp = vk::RenderPassLoadOp::DontCare;
2994             }
2995 
2996             if (unresolveStencil)
2997             {
2998                 stencilLoadOp = vk::RenderPassLoadOp::DontCare;
2999 
3000                 // If VK_EXT_shader_stencil_export is not supported, stencil unresolve is done
3001                 // through a method that requires stencil to have been cleared.
3002                 if (!contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled)
3003                 {
3004                     stencilLoadOp = vk::RenderPassLoadOp::Clear;
3005 
3006                     // Note the aspect is only depth here. That's intentional.
3007                     VkClearValue clearValue = packedClearValues[depthStencilAttachmentIndex];
3008                     clearValue.depthStencil.stencil = 0;
3009                     packedClearValues.store(depthStencilAttachmentIndex, VK_IMAGE_ASPECT_DEPTH_BIT,
3010                                             clearValue);
3011                 }
3012             }
3013 
3014             if (unresolveDepth || unresolveStencil)
3015             {
3016                 mRenderPassDesc.packDepthStencilUnresolveAttachment(unresolveDepth,
3017                                                                     unresolveStencil);
3018             }
3019             else
3020             {
3021                 mRenderPassDesc.removeDepthStencilUnresolveAttachment();
3022             }
3023         }
3024 
3025         renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp);
3026         renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp,
3027                                               stencilStoreOp);
3028     }
3029 
3030     // If render pass description is changed, the previous render pass desc is no longer compatible.
3031     // Tell the context so that the graphics pipelines can be recreated.
3032     //
3033     // Note that render passes are compatible only if the differences are in loadOp/storeOp values,
3034     // or the existence of resolve attachments in single subpass render passes.  The modification
3035     // here can add/remove a subpass, or modify its input attachments.
3036     gl::DrawBufferMask unresolveColorMask = mRenderPassDesc.getColorUnresolveAttachmentMask();
3037     const bool unresolveDepth             = mRenderPassDesc.hasDepthUnresolveAttachment();
3038     const bool unresolveStencil           = mRenderPassDesc.hasStencilUnresolveAttachment();
3039     const bool unresolveChanged           = previousUnresolveColorMask != unresolveColorMask ||
3040                                   previousUnresolveDepth != unresolveDepth ||
3041                                   previousUnresolveStencil != unresolveStencil;
3042     if (unresolveChanged)
3043     {
3044         // Make sure framebuffer is recreated.
3045         releaseCurrentFramebuffer(contextVk);
3046 
3047         mCurrentFramebufferDesc.updateUnresolveMask(MakeUnresolveAttachmentMask(mRenderPassDesc));
3048     }
3049 
3050     vk::MaybeImagelessFramebuffer framebuffer = {};
3051     ANGLE_TRY(
3052         getFramebuffer(contextVk, &framebuffer, nullptr, nullptr, SwapchainResolveMode::Disabled));
3053 
3054     // If deferred clears were used in the render pass, the render area must cover the whole
3055     // framebuffer.
3056     ASSERT(!hasDeferredClears || renderArea == getRotatedCompleteRenderArea(contextVk));
3057 
3058     ANGLE_TRY(contextVk->beginNewRenderPass(
3059         framebuffer, renderArea, mRenderPassDesc, renderPassAttachmentOps, colorIndexVk,
3060         depthStencilAttachmentIndex, packedClearValues, commandBufferOut));
3061     mLastRenderPassQueueSerial = contextVk->getStartedRenderPassCommands().getQueueSerial();
3062 
3063     // Add the images to the renderpass tracking list (through onColorDraw).
3064     vk::PackedAttachmentIndex colorAttachmentIndex(0);
3065     for (size_t colorIndexGL : mState.getColorAttachmentsMask())
3066     {
3067         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
3068         colorRenderTarget->onColorDraw(contextVk, mCurrentFramebufferDesc.getLayerCount(),
3069                                        colorAttachmentIndex);
3070         ++colorAttachmentIndex;
3071     }
3072 
3073     if (depthStencilRenderTarget)
3074     {
3075         // This must be called after hasDefined*Content() since it will set content to valid.  If
3076         // the attachment ends up not used in the render pass, contents will be marked undefined at
3077         // endRenderPass.  The actual layout determination is also deferred until the same time.
3078         depthStencilRenderTarget->onDepthStencilDraw(contextVk,
3079                                                      mCurrentFramebufferDesc.getLayerCount());
3080     }
3081 
3082     const bool anyUnresolve = unresolveColorMask.any() || unresolveDepth || unresolveStencil;
3083     if (anyUnresolve)
3084     {
3085         // Unresolve attachments if any.
3086         UtilsVk::UnresolveParameters params;
3087         params.unresolveColorMask = unresolveColorMask;
3088         params.unresolveDepth     = unresolveDepth;
3089         params.unresolveStencil   = unresolveStencil;
3090 
3091         ANGLE_TRY(contextVk->getUtils().unresolve(contextVk, this, params));
3092 
3093         // The unresolve subpass has only one draw call.
3094         ANGLE_TRY(contextVk->startNextSubpass());
3095     }
3096 
3097     if (unresolveChanged || anyUnresolve)
3098     {
3099         contextVk->onDrawFramebufferRenderPassDescChange(this, renderPassDescChangedOut);
3100     }
3101 
3102     return angle::Result::Continue;
3103 }
3104 
getRenderArea(ContextVk * contextVk) const3105 gl::Rectangle FramebufferVk::getRenderArea(ContextVk *contextVk) const
3106 {
3107     if (hasDeferredClears())
3108     {
3109         return getRotatedCompleteRenderArea(contextVk);
3110     }
3111     else
3112     {
3113         return getRotatedScissoredRenderArea(contextVk);
3114     }
3115 }
3116 
updateActiveColorMasks(size_t colorIndexGL,bool r,bool g,bool b,bool a)3117 void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
3118 {
3119     gl::BlendStateExt::ColorMaskStorage::SetValueIndexed(
3120         colorIndexGL, gl::BlendStateExt::PackColorMask(r, g, b, a),
3121         &mActiveColorComponentMasksForClear);
3122 }
3123 
getEmulatedAlphaAttachmentMask() const3124 const gl::DrawBufferMask &FramebufferVk::getEmulatedAlphaAttachmentMask() const
3125 {
3126     return mEmulatedAlphaAttachmentMask;
3127 }
3128 
readPixelsImpl(ContextVk * contextVk,const gl::Rectangle & area,const PackPixelsParams & packPixelsParams,VkImageAspectFlagBits copyAspectFlags,RenderTargetVk * renderTarget,void * pixels)3129 angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
3130                                             const gl::Rectangle &area,
3131                                             const PackPixelsParams &packPixelsParams,
3132                                             VkImageAspectFlagBits copyAspectFlags,
3133                                             RenderTargetVk *renderTarget,
3134                                             void *pixels)
3135 {
3136     ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
3137     gl::LevelIndex levelGL = renderTarget->getLevelIndex();
3138     uint32_t layer         = renderTarget->getLayerIndex();
3139     return renderTarget->getImageForCopy().readPixels(contextVk, area, packPixelsParams,
3140                                                       copyAspectFlags, levelGL, layer, pixels);
3141 }
3142 
getReadImageExtents() const3143 gl::Extents FramebufferVk::getReadImageExtents() const
3144 {
3145     RenderTargetVk *readRenderTarget = mRenderTargetCache.getColorRead(mState);
3146     return readRenderTarget->getExtents();
3147 }
3148 
3149 // Return the framebuffer's non-rotated render area.  This is a gl::Rectangle that is based on the
3150 // dimensions of the framebuffer, IS NOT rotated, and IS NOT y-flipped
getNonRotatedCompleteRenderArea() const3151 gl::Rectangle FramebufferVk::getNonRotatedCompleteRenderArea() const
3152 {
3153     const gl::Box &dimensions = mState.getDimensions();
3154     return gl::Rectangle(0, 0, dimensions.width, dimensions.height);
3155 }
3156 
3157 // Return the framebuffer's rotated render area.  This is a gl::Rectangle that is based on the
3158 // dimensions of the framebuffer, IS ROTATED for the draw FBO, and IS NOT y-flipped
3159 //
3160 // Note: Since the rectangle is not scissored (i.e. x and y are guaranteed to be zero), only the
3161 // width and height must be swapped if the rotation is 90 or 270 degrees.
getRotatedCompleteRenderArea(ContextVk * contextVk) const3162 gl::Rectangle FramebufferVk::getRotatedCompleteRenderArea(ContextVk *contextVk) const
3163 {
3164     gl::Rectangle renderArea = getNonRotatedCompleteRenderArea();
3165     if (contextVk->isRotatedAspectRatioForDrawFBO())
3166     {
3167         // The surface is rotated 90/270 degrees.  This changes the aspect ratio of the surface.
3168         std::swap(renderArea.width, renderArea.height);
3169     }
3170     return renderArea;
3171 }
3172 
3173 // Return the framebuffer's scissored and rotated render area.  This is a gl::Rectangle that is
3174 // based on the dimensions of the framebuffer, is clipped to the scissor, IS ROTATED and IS
3175 // Y-FLIPPED for the draw FBO.
3176 //
3177 // Note: Since the rectangle is scissored, it must be fully rotated, and not just have the width
3178 // and height swapped.
getRotatedScissoredRenderArea(ContextVk * contextVk) const3179 gl::Rectangle FramebufferVk::getRotatedScissoredRenderArea(ContextVk *contextVk) const
3180 {
3181     const gl::Rectangle renderArea = getNonRotatedCompleteRenderArea();
3182     bool invertViewport            = contextVk->isViewportFlipEnabledForDrawFBO();
3183     gl::Rectangle scissoredArea    = ClipRectToScissor(contextVk->getState(), renderArea, false);
3184     gl::Rectangle rotatedScissoredArea;
3185     RotateRectangle(contextVk->getRotationDrawFramebuffer(), invertViewport, renderArea.width,
3186                     renderArea.height, scissoredArea, &rotatedScissoredArea);
3187     return rotatedScissoredArea;
3188 }
3189 
getSamples() const3190 GLint FramebufferVk::getSamples() const
3191 {
3192     const gl::FramebufferAttachment *lastAttachment = nullptr;
3193 
3194     for (size_t colorIndexGL : mState.getEnabledDrawBuffers() & mState.getColorAttachmentsMask())
3195     {
3196         const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
3197         ASSERT(color);
3198 
3199         if (color->isRenderToTexture())
3200         {
3201             return color->getSamples();
3202         }
3203 
3204         lastAttachment = color;
3205     }
3206     const gl::FramebufferAttachment *depthStencil = mState.getDepthOrStencilAttachment();
3207     if (depthStencil)
3208     {
3209         if (depthStencil->isRenderToTexture())
3210         {
3211             return depthStencil->getSamples();
3212         }
3213         lastAttachment = depthStencil;
3214     }
3215 
3216     // If none of the attachments are multisampled-render-to-texture, take the sample count from the
3217     // last attachment (any would have worked, as they would all have the same sample count).
3218     return std::max(lastAttachment ? lastAttachment->getSamples() : 1, 1);
3219 }
3220 
flushDeferredClears(ContextVk * contextVk)3221 angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk)
3222 {
3223     if (mDeferredClears.empty())
3224     {
3225         return angle::Result::Continue;
3226     }
3227 
3228     return contextVk->startRenderPass(getRotatedCompleteRenderArea(contextVk), nullptr, nullptr);
3229 }
3230 
switchToFramebufferFetchMode(ContextVk * contextVk,bool hasFramebufferFetch)3231 void FramebufferVk::switchToFramebufferFetchMode(ContextVk *contextVk, bool hasFramebufferFetch)
3232 {
3233     // The switch happens once, and is permanent.
3234     if (mCurrentFramebufferDesc.hasFramebufferFetch() == hasFramebufferFetch)
3235     {
3236         return;
3237     }
3238 
3239     // Make sure framebuffer is recreated.
3240     releaseCurrentFramebuffer(contextVk);
3241     mCurrentFramebufferDesc.setFramebufferFetchMode(hasFramebufferFetch);
3242 
3243     mRenderPassDesc.setFramebufferFetchMode(hasFramebufferFetch);
3244     contextVk->onDrawFramebufferRenderPassDescChange(this, nullptr);
3245 
3246     // Clear the framebuffer cache, as none of the old framebuffers are usable.
3247     if (contextVk->getFeatures().permanentlySwitchToFramebufferFetchMode.enabled)
3248     {
3249         ASSERT(hasFramebufferFetch);
3250         releaseCurrentFramebuffer(contextVk);
3251     }
3252 }
3253 
updateLegacyDither(ContextVk * contextVk)3254 bool FramebufferVk::updateLegacyDither(ContextVk *contextVk)
3255 {
3256     if (contextVk->getFeatures().supportsLegacyDithering.enabled &&
3257         mRenderPassDesc.isLegacyDitherEnabled() != contextVk->isDitherEnabled())
3258     {
3259         mRenderPassDesc.setLegacyDither(contextVk->isDitherEnabled());
3260         return true;
3261     }
3262 
3263     return false;
3264 }
3265 }  // namespace rx
3266