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