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