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