• 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 "libANGLE/Context.h"
16 #include "libANGLE/Display.h"
17 #include "libANGLE/formatutils.h"
18 #include "libANGLE/renderer/renderer_utils.h"
19 #include "libANGLE/renderer/vulkan/ContextVk.h"
20 #include "libANGLE/renderer/vulkan/DisplayVk.h"
21 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
22 #include "libANGLE/renderer/vulkan/RendererVk.h"
23 #include "libANGLE/renderer/vulkan/ResourceVk.h"
24 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
25 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
26 #include "libANGLE/renderer/vulkan/vk_headers.h"
27 #include "libANGLE/trace.h"
28 
29 namespace rx
30 {
31 
32 namespace
33 {
34 constexpr size_t kMinReadPixelsBufferSize = 128000;
35 
36 // Alignment value to accommodate the largest known, for now, uncompressed Vulkan format
37 // VK_FORMAT_R64G64B64A64_SFLOAT, while supporting 3-component types such as
38 // VK_FORMAT_R16G16B16_SFLOAT.
39 constexpr size_t kReadPixelsBufferAlignment = 32 * 3;
40 
41 // Clear values are only used when loadOp=Clear is set in clearWithRenderPassOp.  When starting a
42 // new render pass, the clear value is set to an unlikely value (bright pink) to stand out better
43 // in case of a bug.
44 constexpr VkClearValue kUninitializedClearValue = {{{0.95, 0.05, 0.95, 0.95}}};
45 
46 // The value to assign an alpha channel that's emulated.  The type is unsigned int, though it will
47 // automatically convert to the actual data type.
48 constexpr unsigned int kEmulatedAlphaValue = 1;
49 
HasSrcBlitFeature(RendererVk * renderer,RenderTargetVk * srcRenderTarget)50 bool HasSrcBlitFeature(RendererVk *renderer, RenderTargetVk *srcRenderTarget)
51 {
52     const VkFormat srcFormat = srcRenderTarget->getImageFormat().vkImageFormat;
53     return renderer->hasImageFormatFeatureBits(srcFormat, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
54 }
55 
HasDstBlitFeature(RendererVk * renderer,RenderTargetVk * dstRenderTarget)56 bool HasDstBlitFeature(RendererVk *renderer, RenderTargetVk *dstRenderTarget)
57 {
58     const VkFormat dstFormat = dstRenderTarget->getImageFormat().vkImageFormat;
59     return renderer->hasImageFormatFeatureBits(dstFormat, VK_FORMAT_FEATURE_BLIT_DST_BIT);
60 }
61 
62 // Returns false if destination has any channel the source doesn't.  This means that channel was
63 // emulated and using the Vulkan blit command would overwrite that emulated channel.
AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)64 bool AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
65                                              RenderTargetVk *dstRenderTarget)
66 {
67     const angle::Format &srcFormat = srcRenderTarget->getImageFormat().intendedFormat();
68     const angle::Format &dstFormat = dstRenderTarget->getImageFormat().intendedFormat();
69 
70     // Luminance/alpha formats are not renderable, so they can't have ended up in a framebuffer to
71     // participate in a blit.
72     ASSERT(!dstFormat.isLUMA() && !srcFormat.isLUMA());
73 
74     // All color formats have the red channel.
75     ASSERT(dstFormat.redBits > 0 && srcFormat.redBits > 0);
76 
77     return (dstFormat.greenBits > 0 || srcFormat.greenBits == 0) &&
78            (dstFormat.blueBits > 0 || srcFormat.blueBits == 0) &&
79            (dstFormat.alphaBits > 0 || srcFormat.alphaBits == 0);
80 }
81 
AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk * srcRenderTarget,RenderTargetVk * dstRenderTarget)82 bool AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
83                                                     RenderTargetVk *dstRenderTarget)
84 {
85     const angle::Format &srcFormat = srcRenderTarget->getImageFormat().intendedFormat();
86     const angle::Format &dstFormat = dstRenderTarget->getImageFormat().intendedFormat();
87 
88     return (dstFormat.depthBits > 0 || srcFormat.depthBits == 0) &&
89            (dstFormat.stencilBits > 0 || srcFormat.stencilBits == 0);
90 }
91 }  // anonymous namespace
92 
93 // static
CreateUserFBO(RendererVk * renderer,const gl::FramebufferState & state)94 FramebufferVk *FramebufferVk::CreateUserFBO(RendererVk *renderer, const gl::FramebufferState &state)
95 {
96     return new FramebufferVk(renderer, state, nullptr);
97 }
98 
99 // static
CreateDefaultFBO(RendererVk * renderer,const gl::FramebufferState & state,WindowSurfaceVk * backbuffer)100 FramebufferVk *FramebufferVk::CreateDefaultFBO(RendererVk *renderer,
101                                                const gl::FramebufferState &state,
102                                                WindowSurfaceVk *backbuffer)
103 {
104     return new FramebufferVk(renderer, state, backbuffer);
105 }
106 
FramebufferVk(RendererVk * renderer,const gl::FramebufferState & state,WindowSurfaceVk * backbuffer)107 FramebufferVk::FramebufferVk(RendererVk *renderer,
108                              const gl::FramebufferState &state,
109                              WindowSurfaceVk *backbuffer)
110     : FramebufferImpl(state),
111       mBackbuffer(backbuffer),
112       mFramebuffer(nullptr),
113       mActiveColorComponents(0),
114       mSupportDepthStencilFeedbackLoops(
115           renderer->getFeatures().supportDepthStencilRenderingFeedbackLoops.enabled)
116 {
117     mReadPixelBuffer.init(renderer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, kReadPixelsBufferAlignment,
118                           kMinReadPixelsBufferSize, true);
119 }
120 
121 FramebufferVk::~FramebufferVk() = default;
122 
clearCache(ContextVk * contextVk)123 void FramebufferVk::clearCache(ContextVk *contextVk)
124 {
125     for (auto &entry : mFramebufferCache)
126     {
127         vk::FramebufferHelper &tmpFB = entry.second;
128         tmpFB.release(contextVk);
129     }
130     mFramebufferCache.clear();
131 }
132 
destroy(const gl::Context * context)133 void FramebufferVk::destroy(const gl::Context *context)
134 {
135     ContextVk *contextVk = vk::GetImpl(context);
136 
137     mReadPixelBuffer.release(contextVk->getRenderer());
138     clearCache(contextVk);
139 }
140 
discard(const gl::Context * context,size_t count,const GLenum * attachments)141 angle::Result FramebufferVk::discard(const gl::Context *context,
142                                      size_t count,
143                                      const GLenum *attachments)
144 {
145     return invalidate(context, count, attachments);
146 }
147 
invalidate(const gl::Context * context,size_t count,const GLenum * attachments)148 angle::Result FramebufferVk::invalidate(const gl::Context *context,
149                                         size_t count,
150                                         const GLenum *attachments)
151 {
152     // TODO(jmadill): Re-enable. See http://anglebug.com/4444
153     return angle::Result::Continue;
154 }
155 
invalidateSub(const gl::Context * context,size_t count,const GLenum * attachments,const gl::Rectangle & area)156 angle::Result FramebufferVk::invalidateSub(const gl::Context *context,
157                                            size_t count,
158                                            const GLenum *attachments,
159                                            const gl::Rectangle &area)
160 {
161     // TODO(jmadill): Re-enable. See http://anglebug.com/4444
162     return angle::Result::Continue;
163 }
164 
clear(const gl::Context * context,GLbitfield mask)165 angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
166 {
167     ContextVk *contextVk = vk::GetImpl(context);
168 
169     bool clearColor   = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT));
170     bool clearDepth   = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT));
171     bool clearStencil = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_STENCIL_BUFFER_BIT));
172     gl::DrawBufferMask clearColorBuffers;
173     if (clearColor)
174     {
175         clearColorBuffers = mState.getEnabledDrawBuffers();
176     }
177 
178     const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
179     const VkClearDepthStencilValue &clearDepthStencilValue =
180         contextVk->getClearDepthStencilValue().depthStencil;
181 
182     return clearImpl(context, clearColorBuffers, clearDepth, clearStencil, clearColorValue,
183                      clearDepthStencilValue);
184 }
185 
clearImpl(const gl::Context * context,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)186 angle::Result FramebufferVk::clearImpl(const gl::Context *context,
187                                        gl::DrawBufferMask clearColorBuffers,
188                                        bool clearDepth,
189                                        bool clearStencil,
190                                        const VkClearColorValue &clearColorValue,
191                                        const VkClearDepthStencilValue &clearDepthStencilValue)
192 {
193     ContextVk *contextVk = vk::GetImpl(context);
194 
195     const gl::Rectangle scissoredRenderArea = getScissoredRenderArea(contextVk);
196 
197     // Discard clear altogether if scissor has 0 width or height.
198     if (scissoredRenderArea.width == 0 || scissoredRenderArea.height == 0)
199     {
200         return angle::Result::Continue;
201     }
202 
203     // We can sometimes get to a clear operation with other pending clears (e.g. for emulated
204     // formats). Ensure the prior clears happen before the new clear. Note that we do not defer
205     // clears for scissored operations. Note that some clears may be redundant with the current
206     // clear. Due to complexity we haven't implemented de-duplication here.
207     ANGLE_TRY(flushDeferredClears(contextVk, scissoredRenderArea));
208 
209     // This function assumes that only enabled attachments are asked to be cleared.
210     ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
211 
212     // Adjust clear behavior based on whether the respective attachments are present; if asked to
213     // clear a non-existent attachment, don't attempt to clear it.
214 
215     VkColorComponentFlags colorMaskFlags = contextVk->getClearColorMask();
216     bool clearColor                      = clearColorBuffers.any();
217 
218     const gl::FramebufferAttachment *depthAttachment = mState.getDepthAttachment();
219     clearDepth                                       = clearDepth && depthAttachment;
220     ASSERT(!clearDepth || depthAttachment->isAttached());
221 
222     const gl::FramebufferAttachment *stencilAttachment = mState.getStencilAttachment();
223     clearStencil                                       = clearStencil && stencilAttachment;
224     ASSERT(!clearStencil || stencilAttachment->isAttached());
225 
226     uint8_t stencilMask =
227         static_cast<uint8_t>(contextVk->getState().getDepthStencilState().stencilWritemask);
228 
229     // The front-end should ensure we don't attempt to clear color if all channels are masked.
230     ASSERT(!clearColor || colorMaskFlags != 0);
231     // The front-end should ensure we don't attempt to clear depth if depth write is disabled.
232     ASSERT(!clearDepth || contextVk->getState().getDepthStencilState().depthMask);
233     // The front-end should ensure we don't attempt to clear stencil if all bits are masked.
234     ASSERT(!clearStencil || stencilMask != 0);
235 
236     bool scissoredClear = scissoredRenderArea != getCompleteRenderArea();
237 
238     // Special case for rendering feedback loops: clears are always valid in GL since they don't
239     // sample from any textures.
240     if ((clearDepth || clearStencil) && mState.hasDepthStencilFeedbackLoop())
241     {
242         // We currently don't handle scissored clears with rendering feedback loops.
243         ANGLE_VK_CHECK(contextVk, !scissoredClear, VK_ERROR_INCOMPATIBLE_DRIVER);
244 
245         RenderTargetVk *depthStencilRT = mRenderTargetCache.getDepthStencil(true);
246         vk::ImageHelper &image         = depthStencilRT->getImage();
247 
248         vk::CommandBuffer *commandBuffer;
249         ANGLE_TRY(
250             contextVk->onImageWrite(image.getAspectFlags(), vk::ImageLayout::TransferDst, &image));
251         ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
252 
253         VkImageSubresourceRange range;
254         range.aspectMask     = image.getAspectFlags();
255         range.baseMipLevel   = depthStencilRT->getLevelIndex();
256         range.levelCount     = 1;
257         range.baseArrayLayer = depthStencilRT->getLayerIndex();
258         range.layerCount     = 1;
259 
260         commandBuffer->clearDepthStencilImage(image.getImage(),
261                                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
262                                               clearDepthStencilValue, 1, &range);
263         clearDepth   = false;
264         clearStencil = false;
265     }
266 
267     // If there is nothing to clear, return right away (for example, if asked to clear depth, but
268     // there is no depth attachment).
269     if (!clearColor && !clearDepth && !clearStencil)
270     {
271         return angle::Result::Continue;
272     }
273 
274     // We can use render pass load ops if clearing depth, unmasked color or unmasked stencil.  If
275     // there's a depth mask, depth clearing is already disabled.
276     bool maskedClearColor =
277         clearColor && (mActiveColorComponents & colorMaskFlags) != mActiveColorComponents;
278     bool maskedClearStencil = clearStencil && stencilMask != 0xFF;
279 
280     bool clearColorWithRenderPassLoadOp   = clearColor && !maskedClearColor && !scissoredClear;
281     bool clearDepthWithRenderPassLoadOp   = clearDepth && !scissoredClear;
282     bool clearStencilWithRenderPassLoadOp = clearStencil && !maskedClearStencil && !scissoredClear;
283 
284     // At least one of color, depth or stencil should be clearable with render pass loadOp for us
285     // to use this clear path.
286     bool clearAnyWithRenderPassLoadOp = clearColorWithRenderPassLoadOp ||
287                                         clearDepthWithRenderPassLoadOp ||
288                                         clearStencilWithRenderPassLoadOp;
289 
290     if (clearAnyWithRenderPassLoadOp)
291     {
292         // Clearing color is indicated by the set bits in this mask.  If not clearing colors with
293         // render pass loadOp, the default value of all-zeros means the clear is not done in
294         // clearWithRenderPassOp below.  In that case, only clear depth/stencil with render pass
295         // loadOp.
296         gl::DrawBufferMask clearBuffersWithRenderPassLoadOp;
297         if (clearColorWithRenderPassLoadOp)
298         {
299             clearBuffersWithRenderPassLoadOp = clearColorBuffers;
300         }
301 
302         clearWithRenderPassOp(clearBuffersWithRenderPassLoadOp, clearDepthWithRenderPassLoadOp,
303                               clearStencilWithRenderPassLoadOp, clearColorValue,
304                               clearDepthStencilValue);
305 
306         // Fallback to other methods for whatever isn't cleared here.
307         if (clearColorWithRenderPassLoadOp)
308         {
309             clearColorBuffers.reset();
310             clearColor = false;
311         }
312         if (clearDepthWithRenderPassLoadOp)
313         {
314             clearDepth = false;
315         }
316         if (clearStencilWithRenderPassLoadOp)
317         {
318             clearStencil = false;
319         }
320 
321         // If nothing left to clear, early out.
322         if (!clearColor && !clearStencil)
323         {
324             return angle::Result::Continue;
325         }
326     }
327 
328     if (scissoredClear && !maskedClearColor && !maskedClearStencil)
329     {
330         return clearImmediatelyWithRenderPassOp(contextVk, scissoredRenderArea, clearColorBuffers,
331                                                 clearDepth, clearStencil, clearColorValue,
332                                                 clearDepthStencilValue);
333     }
334 
335     // The most costly clear mode is when we need to mask out specific color channels or stencil
336     // bits. This can only be done with a draw call.
337     return clearWithDraw(contextVk, scissoredRenderArea, clearColorBuffers, clearDepth,
338                          clearStencil, colorMaskFlags, stencilMask, clearColorValue,
339                          clearDepthStencilValue);
340 }
341 
clearBufferfv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLfloat * values)342 angle::Result FramebufferVk::clearBufferfv(const gl::Context *context,
343                                            GLenum buffer,
344                                            GLint drawbuffer,
345                                            const GLfloat *values)
346 {
347     VkClearValue clearValue = {};
348 
349     bool clearDepth = false;
350     gl::DrawBufferMask clearColorBuffers;
351 
352     if (buffer == GL_DEPTH)
353     {
354         clearDepth                    = true;
355         clearValue.depthStencil.depth = values[0];
356     }
357     else
358     {
359         clearColorBuffers.set(drawbuffer);
360         clearValue.color.float32[0] = values[0];
361         clearValue.color.float32[1] = values[1];
362         clearValue.color.float32[2] = values[2];
363         clearValue.color.float32[3] = values[3];
364     }
365 
366     return clearImpl(context, clearColorBuffers, clearDepth, false, clearValue.color,
367                      clearValue.depthStencil);
368 }
369 
clearBufferuiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLuint * values)370 angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context,
371                                             GLenum buffer,
372                                             GLint drawbuffer,
373                                             const GLuint *values)
374 {
375     VkClearValue clearValue = {};
376 
377     gl::DrawBufferMask clearColorBuffers;
378     clearColorBuffers.set(drawbuffer);
379 
380     clearValue.color.uint32[0] = values[0];
381     clearValue.color.uint32[1] = values[1];
382     clearValue.color.uint32[2] = values[2];
383     clearValue.color.uint32[3] = values[3];
384 
385     return clearImpl(context, clearColorBuffers, false, false, clearValue.color,
386                      clearValue.depthStencil);
387 }
388 
clearBufferiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLint * values)389 angle::Result FramebufferVk::clearBufferiv(const gl::Context *context,
390                                            GLenum buffer,
391                                            GLint drawbuffer,
392                                            const GLint *values)
393 {
394     VkClearValue clearValue = {};
395 
396     bool clearStencil = false;
397     gl::DrawBufferMask clearColorBuffers;
398 
399     if (buffer == GL_STENCIL)
400     {
401         clearStencil = true;
402         clearValue.depthStencil.stencil =
403             gl::clamp(values[0], 0, std::numeric_limits<uint8_t>::max());
404     }
405     else
406     {
407         clearColorBuffers.set(drawbuffer);
408         clearValue.color.int32[0] = values[0];
409         clearValue.color.int32[1] = values[1];
410         clearValue.color.int32[2] = values[2];
411         clearValue.color.int32[3] = values[3];
412     }
413 
414     return clearImpl(context, clearColorBuffers, false, clearStencil, clearValue.color,
415                      clearValue.depthStencil);
416 }
417 
clearBufferfi(const gl::Context * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)418 angle::Result FramebufferVk::clearBufferfi(const gl::Context *context,
419                                            GLenum buffer,
420                                            GLint drawbuffer,
421                                            GLfloat depth,
422                                            GLint stencil)
423 {
424     VkClearValue clearValue = {};
425 
426     clearValue.depthStencil.depth   = depth;
427     clearValue.depthStencil.stencil = gl::clamp(stencil, 0, std::numeric_limits<uint8_t>::max());
428 
429     return clearImpl(context, gl::DrawBufferMask(), true, true, clearValue.color,
430                      clearValue.depthStencil);
431 }
432 
getImplementationColorReadFormat(const gl::Context * context) const433 const gl::InternalFormat &FramebufferVk::getImplementationColorReadFormat(
434     const gl::Context *context) const
435 {
436     ContextVk *contextVk       = vk::GetImpl(context);
437     GLenum sizedFormat         = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
438     const vk::Format &vkFormat = contextVk->getRenderer()->getFormat(sizedFormat);
439     GLenum implFormat          = vkFormat.actualImageFormat().fboImplementationInternalFormat;
440     return gl::GetSizedInternalFormatInfo(implFormat);
441 }
442 
readPixels(const gl::Context * context,const gl::Rectangle & area,GLenum format,GLenum type,void * pixels)443 angle::Result FramebufferVk::readPixels(const gl::Context *context,
444                                         const gl::Rectangle &area,
445                                         GLenum format,
446                                         GLenum type,
447                                         void *pixels)
448 {
449     // Clip read area to framebuffer.
450     const gl::Extents &fbSize = getState().getReadPixelsAttachment(format)->getSize();
451     const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
452     ContextVk *contextVk = vk::GetImpl(context);
453 
454     gl::Rectangle clippedArea;
455     if (!ClipRectangle(area, fbRect, &clippedArea))
456     {
457         // nothing to read
458         return angle::Result::Continue;
459     }
460 
461     // Flush any deferred clears.
462     ANGLE_TRY(flushDeferredClears(contextVk, fbRect));
463 
464     const gl::State &glState = contextVk->getState();
465     gl::Buffer *packBuffer   = glState.getTargetBuffer(gl::BufferBinding::PixelPack);
466 
467     GLuint outputSkipBytes = 0;
468     PackPixelsParams params;
469     ANGLE_TRY(vk::ImageHelper::GetReadPixelsParams(contextVk, glState.getPackState(), packBuffer,
470                                                    format, type, area, clippedArea, &params,
471                                                    &outputSkipBytes));
472 
473     bool flipY = contextVk->isViewportFlipEnabledForReadFBO();
474     switch (params.rotation = contextVk->getRotationReadFramebuffer())
475     {
476         case SurfaceRotation::Identity:
477             // Do not rotate gl_Position (surface matches the device's orientation):
478             if (flipY)
479             {
480                 params.area.y = fbRect.height - clippedArea.y - clippedArea.height;
481             }
482             break;
483         case SurfaceRotation::Rotated90Degrees:
484             // Rotate gl_Position 90 degrees:
485             params.area.x = clippedArea.y;
486             params.area.y =
487                 flipY ? clippedArea.x : fbRect.width - clippedArea.x - clippedArea.width;
488             std::swap(params.area.width, params.area.height);
489             break;
490         case SurfaceRotation::Rotated180Degrees:
491             // Rotate gl_Position 180 degrees:
492             params.area.x = fbRect.width - clippedArea.x - clippedArea.width;
493             params.area.y =
494                 flipY ? clippedArea.y : fbRect.height - clippedArea.y - clippedArea.height;
495             break;
496         case SurfaceRotation::Rotated270Degrees:
497             // Rotate gl_Position 270 degrees:
498             params.area.x = fbRect.height - clippedArea.y - clippedArea.height;
499             params.area.y =
500                 flipY ? fbRect.width - clippedArea.x - clippedArea.width : clippedArea.x;
501             std::swap(params.area.width, params.area.height);
502             break;
503         default:
504             UNREACHABLE();
505             break;
506     }
507     if (flipY)
508     {
509         params.reverseRowOrder = !params.reverseRowOrder;
510     }
511 
512     ANGLE_TRY(readPixelsImpl(contextVk, params.area, params, getReadPixelsAspectFlags(format),
513                              getReadPixelsRenderTarget(format),
514                              static_cast<uint8_t *>(pixels) + outputSkipBytes));
515     mReadPixelBuffer.releaseInFlightBuffers(contextVk);
516     return angle::Result::Continue;
517 }
518 
getDepthStencilRenderTarget() const519 RenderTargetVk *FramebufferVk::getDepthStencilRenderTarget() const
520 {
521     // If we mask out depth/stencil feedback loops, do not allow the user to access the looped DS
522     // render target. Passing "false" to getDepthStencil forces a return of "nullptr" for loops.
523     return mRenderTargetCache.getDepthStencil(!mSupportDepthStencilFeedbackLoops);
524 }
525 
getColorDrawRenderTarget(size_t colorIndex) const526 RenderTargetVk *FramebufferVk::getColorDrawRenderTarget(size_t colorIndex) const
527 {
528     RenderTargetVk *renderTarget = mRenderTargetCache.getColorDraw(mState, colorIndex);
529     ASSERT(renderTarget && renderTarget->getImage().valid());
530     return renderTarget;
531 }
532 
getColorReadRenderTarget() const533 RenderTargetVk *FramebufferVk::getColorReadRenderTarget() const
534 {
535     RenderTargetVk *renderTarget = mRenderTargetCache.getColorRead(mState);
536     ASSERT(renderTarget && renderTarget->getImage().valid());
537     return renderTarget;
538 }
539 
getReadPixelsRenderTarget(GLenum format) const540 RenderTargetVk *FramebufferVk::getReadPixelsRenderTarget(GLenum format) const
541 {
542     switch (format)
543     {
544         case GL_DEPTH_COMPONENT:
545         case GL_STENCIL_INDEX_OES:
546             return getDepthStencilRenderTarget();
547         default:
548             return getColorReadRenderTarget();
549     }
550 }
551 
getReadPixelsAspectFlags(GLenum format) const552 VkImageAspectFlagBits FramebufferVk::getReadPixelsAspectFlags(GLenum format) const
553 {
554     switch (format)
555     {
556         case GL_DEPTH_COMPONENT:
557             return VK_IMAGE_ASPECT_DEPTH_BIT;
558         case GL_STENCIL_INDEX_OES:
559             return VK_IMAGE_ASPECT_STENCIL_BIT;
560         default:
561             return VK_IMAGE_ASPECT_COLOR_BIT;
562     }
563 }
564 
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)565 angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
566                                              const gl::Rectangle &sourceArea,
567                                              const gl::Rectangle &destArea,
568                                              RenderTargetVk *readRenderTarget,
569                                              RenderTargetVk *drawRenderTarget,
570                                              GLenum filter,
571                                              bool colorBlit,
572                                              bool depthBlit,
573                                              bool stencilBlit,
574                                              bool flipX,
575                                              bool flipY)
576 {
577     // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
578     // it should never be the case that both color and depth/stencil need to be blitted at
579     // at the same time.
580     ASSERT(colorBlit != (depthBlit || stencilBlit));
581 
582     vk::ImageHelper *srcImage = &readRenderTarget->getImage();
583     vk::ImageHelper *dstImage = drawRenderTarget->getImageForWrite(contextVk);
584 
585     VkImageAspectFlags imageAspectMask = srcImage->getAspectFlags();
586     VkImageAspectFlags blitAspectMask  = imageAspectMask;
587 
588     // Remove depth or stencil aspects if they are not requested to be blitted.
589     if (!depthBlit)
590     {
591         blitAspectMask &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
592     }
593     if (!stencilBlit)
594     {
595         blitAspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
596     }
597 
598     vk::CommandBuffer *commandBuffer = nullptr;
599     ANGLE_TRY(contextVk->onImageRead(imageAspectMask, vk::ImageLayout::TransferSrc, srcImage));
600     ANGLE_TRY(contextVk->onImageWrite(imageAspectMask, vk::ImageLayout::TransferDst, dstImage));
601     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
602 
603     VkImageBlit blit                   = {};
604     blit.srcSubresource.aspectMask     = blitAspectMask;
605     blit.srcSubresource.mipLevel       = readRenderTarget->getLevelIndex();
606     blit.srcSubresource.baseArrayLayer = readRenderTarget->getLayerIndex();
607     blit.srcSubresource.layerCount     = 1;
608     blit.srcOffsets[0]                 = {sourceArea.x0(), sourceArea.y0(), 0};
609     blit.srcOffsets[1]                 = {sourceArea.x1(), sourceArea.y1(), 1};
610     blit.dstSubresource.aspectMask     = blitAspectMask;
611     blit.dstSubresource.mipLevel       = drawRenderTarget->getLevelIndex();
612     blit.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
613     blit.dstSubresource.layerCount     = 1;
614     blit.dstOffsets[0]                 = {destArea.x0(), destArea.y0(), 0};
615     blit.dstOffsets[1]                 = {destArea.x1(), destArea.y1(), 1};
616 
617     commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
618                              dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
619                              gl_vk::GetFilter(filter));
620 
621     return angle::Result::Continue;
622 }
623 
blit(const gl::Context * context,const gl::Rectangle & sourceAreaIn,const gl::Rectangle & destAreaIn,GLbitfield mask,GLenum filter)624 angle::Result FramebufferVk::blit(const gl::Context *context,
625                                   const gl::Rectangle &sourceAreaIn,
626                                   const gl::Rectangle &destAreaIn,
627                                   GLbitfield mask,
628                                   GLenum filter)
629 {
630     ContextVk *contextVk = vk::GetImpl(context);
631     RendererVk *renderer = contextVk->getRenderer();
632     UtilsVk &utilsVk     = contextVk->getUtils();
633 
634     // We can sometimes end up in a blit with some clear commands saved. Ensure all clear commands
635     // are issued before we issue the blit command.
636     ANGLE_TRY(flushDeferredClears(contextVk, getCompleteRenderArea()));
637 
638     const gl::State &glState              = contextVk->getState();
639     const gl::Framebuffer *srcFramebuffer = glState.getReadFramebuffer();
640 
641     const bool blitColorBuffer   = (mask & GL_COLOR_BUFFER_BIT) != 0;
642     const bool blitDepthBuffer   = (mask & GL_DEPTH_BUFFER_BIT) != 0;
643     const bool blitStencilBuffer = (mask & GL_STENCIL_BUFFER_BIT) != 0;
644 
645     const bool isResolve =
646         srcFramebuffer->getCachedSamples(context, gl::AttachmentSampleType::Resource) > 1;
647 
648     FramebufferVk *srcFramebufferVk    = vk::GetImpl(srcFramebuffer);
649     const bool srcFramebufferFlippedY  = contextVk->isViewportFlipEnabledForReadFBO();
650     const bool destFramebufferFlippedY = contextVk->isViewportFlipEnabledForDrawFBO();
651 
652     gl::Rectangle sourceArea = sourceAreaIn;
653     gl::Rectangle destArea   = destAreaIn;
654 
655     // Note: GLES (all 3.x versions) require source and dest area to be identical when
656     // resolving.
657     ASSERT(!isResolve ||
658            (sourceArea.x == destArea.x && sourceArea.y == destArea.y &&
659             sourceArea.width == destArea.width && sourceArea.height == destArea.height));
660 
661     const gl::Rectangle srcFramebufferDimensions =
662         srcFramebufferVk->mState.getDimensions().toRect();
663 
664     // If the destination is flipped in either direction, we will flip the source instead so that
665     // the destination area is always unflipped.
666     sourceArea = sourceArea.flip(destArea.isReversedX(), destArea.isReversedY());
667     destArea   = destArea.removeReversal();
668 
669     // Calculate the stretch factor prior to any clipping, as it needs to remain constant.
670     const float stretch[2] = {
671         std::abs(sourceArea.width / static_cast<float>(destArea.width)),
672         std::abs(sourceArea.height / static_cast<float>(destArea.height)),
673     };
674 
675     // First, clip the source area to framebuffer.  That requires transforming the dest area to
676     // match the clipped source.
677     gl::Rectangle absSourceArea = sourceArea.removeReversal();
678     gl::Rectangle clippedSourceArea;
679     if (!gl::ClipRectangle(srcFramebufferDimensions, absSourceArea, &clippedSourceArea))
680     {
681         return angle::Result::Continue;
682     }
683 
684     // Resize the destination area based on the new size of source.  Note again that stretch is
685     // calculated as SrcDimension/DestDimension.
686     gl::Rectangle srcClippedDestArea;
687     if (isResolve)
688     {
689         // Source and dest areas are identical in resolve.
690         srcClippedDestArea = clippedSourceArea;
691     }
692     else if (clippedSourceArea == absSourceArea)
693     {
694         // If there was no clipping, keep dest area as is.
695         srcClippedDestArea = destArea;
696     }
697     else
698     {
699         // Shift dest area's x0,y0,x1,y1 by as much as the source area's got shifted (taking
700         // stretching into account)
701         float x0Shift = std::round((clippedSourceArea.x - absSourceArea.x) / stretch[0]);
702         float y0Shift = std::round((clippedSourceArea.y - absSourceArea.y) / stretch[1]);
703         float x1Shift = std::round((absSourceArea.x1() - clippedSourceArea.x1()) / stretch[0]);
704         float y1Shift = std::round((absSourceArea.y1() - clippedSourceArea.y1()) / stretch[1]);
705 
706         // If the source area was reversed in any direction, the shift should be applied in the
707         // opposite direction as well.
708         if (sourceArea.isReversedX())
709         {
710             std::swap(x0Shift, x1Shift);
711         }
712 
713         if (sourceArea.isReversedY())
714         {
715             std::swap(y0Shift, y1Shift);
716         }
717 
718         srcClippedDestArea.x = destArea.x0() + static_cast<int>(x0Shift);
719         srcClippedDestArea.y = destArea.y0() + static_cast<int>(y0Shift);
720         int x1               = destArea.x1() - static_cast<int>(x1Shift);
721         int y1               = destArea.y1() - static_cast<int>(y1Shift);
722 
723         srcClippedDestArea.width  = x1 - srcClippedDestArea.x;
724         srcClippedDestArea.height = y1 - srcClippedDestArea.y;
725     }
726 
727     // If framebuffers are flipped in Y, flip the source and dest area (which define the
728     // transformation regardless of clipping), as well as the blit area (which is the clipped
729     // dest area).
730     if (srcFramebufferFlippedY)
731     {
732         sourceArea.y      = srcFramebufferDimensions.height - sourceArea.y;
733         sourceArea.height = -sourceArea.height;
734     }
735     if (destFramebufferFlippedY)
736     {
737         destArea.y      = mState.getDimensions().height - destArea.y;
738         destArea.height = -destArea.height;
739 
740         srcClippedDestArea.y =
741             mState.getDimensions().height - srcClippedDestArea.y - srcClippedDestArea.height;
742     }
743 
744     const bool flipX = sourceArea.isReversedX() != destArea.isReversedX();
745     const bool flipY = sourceArea.isReversedY() != destArea.isReversedY();
746 
747     // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve.
748     ASSERT(!isResolve ||
749            (flipX == false && flipY == (srcFramebufferFlippedY != destFramebufferFlippedY)));
750 
751     // Again, transfer the destination flip to source, so dest is unflipped.  Note that destArea
752     // was not reversed until the final possible Y-flip.
753     ASSERT(!destArea.isReversedX());
754     sourceArea = sourceArea.flip(false, destArea.isReversedY());
755     destArea   = destArea.removeReversal();
756 
757     // Clip the destination area to the framebuffer size and scissor.  Note that we don't care
758     // about the source area anymore.  The offset translation is done based on the original source
759     // and destination rectangles.  The stretch factor is already calculated as well.
760     gl::Rectangle blitArea;
761     if (!gl::ClipRectangle(getScissoredRenderArea(contextVk), srcClippedDestArea, &blitArea))
762     {
763         return angle::Result::Continue;
764     }
765 
766     bool noClip = blitArea == destArea && stretch[0] == 1.0f && stretch[1] == 1.0f;
767     bool noFlip = !flipX && !flipY;
768     bool disableFlippingBlitWithCommand =
769         contextVk->getRenderer()->getFeatures().disableFlippingBlitWithCommand.enabled;
770 
771     UtilsVk::BlitResolveParameters params;
772     params.srcOffset[0]  = sourceArea.x;
773     params.srcOffset[1]  = sourceArea.y;
774     params.destOffset[0] = destArea.x;
775     params.destOffset[1] = destArea.y;
776     params.stretch[0]    = stretch[0];
777     params.stretch[1]    = stretch[1];
778     params.srcExtents[0] = srcFramebufferDimensions.width;
779     params.srcExtents[1] = srcFramebufferDimensions.height;
780     params.blitArea      = blitArea;
781     params.linear        = filter == GL_LINEAR;
782     params.flipX         = flipX;
783     params.flipY         = flipY;
784 
785     if (blitColorBuffer)
786     {
787         RenderTargetVk *readRenderTarget = srcFramebufferVk->getColorReadRenderTarget();
788         params.srcLayer                  = readRenderTarget->getLayerIndex();
789 
790         // Multisampled images are not allowed to have mips.
791         ASSERT(!isResolve || readRenderTarget->getLevelIndex() == 0);
792 
793         // If there was no clipping and the format capabilities allow us, use Vulkan's builtin blit.
794         // The reason clipping is prohibited in this path is that due to rounding errors, it would
795         // be hard to guarantee the image stretching remains perfect.  That also allows us not to
796         // have to transform back the dest clipping to source.
797         //
798         // For simplicity, we either blit all render targets with a Vulkan command, or none.
799         bool canBlitWithCommand = !isResolve && noClip &&
800                                   (noFlip || !disableFlippingBlitWithCommand) &&
801                                   HasSrcBlitFeature(renderer, readRenderTarget);
802         bool areChannelsBlitCompatible = true;
803         for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
804         {
805             RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
806             canBlitWithCommand =
807                 canBlitWithCommand && HasDstBlitFeature(renderer, drawRenderTarget);
808             areChannelsBlitCompatible =
809                 areChannelsBlitCompatible &&
810                 AreSrcAndDstColorChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
811         }
812 
813         if (canBlitWithCommand && areChannelsBlitCompatible)
814         {
815             for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
816             {
817                 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
818                 ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
819                                           drawRenderTarget, filter, true, false, false, flipX,
820                                           flipY));
821             }
822         }
823         // If we're not flipping, use Vulkan's builtin resolve.
824         else if (isResolve && !flipX && !flipY && areChannelsBlitCompatible)
825         {
826             ANGLE_TRY(resolveColorWithCommand(contextVk, params, &readRenderTarget->getImage()));
827         }
828         // Otherwise use a shader to do blit or resolve.
829         else
830         {
831             const vk::ImageView *readImageView = nullptr;
832             ANGLE_TRY(readRenderTarget->getImageView(contextVk, &readImageView));
833             readRenderTarget->retainImageViews(contextVk);
834             ANGLE_TRY(utilsVk.colorBlitResolve(contextVk, this, &readRenderTarget->getImage(),
835                                                readImageView, params));
836         }
837     }
838 
839     if (blitDepthBuffer || blitStencilBuffer)
840     {
841         RenderTargetVk *readRenderTarget = srcFramebufferVk->getDepthStencilRenderTarget();
842         RenderTargetVk *drawRenderTarget = mRenderTargetCache.getDepthStencil(true);
843         params.srcLayer                  = readRenderTarget->getLayerIndex();
844 
845         // Multisampled images are not allowed to have mips.
846         ASSERT(!isResolve || readRenderTarget->getLevelIndex() == 0);
847 
848         // Similarly, only blit if there's been no clipping.
849         bool canBlitWithCommand = !isResolve && noClip &&
850                                   (noFlip || !disableFlippingBlitWithCommand) &&
851                                   HasSrcBlitFeature(renderer, readRenderTarget) &&
852                                   HasDstBlitFeature(renderer, drawRenderTarget);
853         bool areChannelsBlitCompatible =
854             AreSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
855 
856         if (canBlitWithCommand && areChannelsBlitCompatible)
857         {
858             ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
859                                       drawRenderTarget, filter, false, blitDepthBuffer,
860                                       blitStencilBuffer, flipX, flipY));
861         }
862         else
863         {
864             // Create depth- and stencil-only views for reading.
865             vk::DeviceScoped<vk::ImageView> depthView(contextVk->getDevice());
866             vk::DeviceScoped<vk::ImageView> stencilView(contextVk->getDevice());
867 
868             vk::ImageHelper *depthStencilImage = &readRenderTarget->getImage();
869             uint32_t levelIndex                = readRenderTarget->getLevelIndex();
870             uint32_t layerIndex                = readRenderTarget->getLayerIndex();
871             gl::TextureType textureType = vk::Get2DTextureType(depthStencilImage->getLayerCount(),
872                                                                depthStencilImage->getSamples());
873 
874             if (blitDepthBuffer)
875             {
876                 ANGLE_TRY(depthStencilImage->initLayerImageView(
877                     contextVk, textureType, VK_IMAGE_ASPECT_DEPTH_BIT, gl::SwizzleState(),
878                     &depthView.get(), levelIndex, 1, layerIndex, 1));
879             }
880 
881             if (blitStencilBuffer)
882             {
883                 ANGLE_TRY(depthStencilImage->initLayerImageView(
884                     contextVk, textureType, VK_IMAGE_ASPECT_STENCIL_BIT, gl::SwizzleState(),
885                     &stencilView.get(), levelIndex, 1, layerIndex, 1));
886             }
887 
888             // If shader stencil export is not possible, defer stencil blit/stencil to another pass.
889             bool hasShaderStencilExport =
890                 contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled;
891 
892             // Blit depth. If shader stencil export is present, blit stencil as well.
893             if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport))
894             {
895                 const vk::ImageView *depth = blitDepthBuffer ? &depthView.get() : nullptr;
896                 const vk::ImageView *stencil =
897                     blitStencilBuffer && hasShaderStencilExport ? &stencilView.get() : nullptr;
898 
899                 ANGLE_TRY(utilsVk.depthStencilBlitResolve(contextVk, this, depthStencilImage, depth,
900                                                           stencil, params));
901             }
902 
903             // If shader stencil export is not present, blit stencil through a different path.
904             if (blitStencilBuffer && !hasShaderStencilExport)
905             {
906                 ANGLE_TRY(utilsVk.stencilBlitResolveNoShaderExport(
907                     contextVk, this, depthStencilImage, &stencilView.get(), params));
908             }
909 
910             vk::ImageView depthViewObject   = depthView.release();
911             vk::ImageView stencilViewObject = stencilView.release();
912 
913             contextVk->addGarbage(&depthViewObject);
914             contextVk->addGarbage(&stencilViewObject);
915         }
916     }
917 
918     return angle::Result::Continue;
919 }  // namespace rx
920 
resolveColorWithCommand(ContextVk * contextVk,const UtilsVk::BlitResolveParameters & params,vk::ImageHelper * srcImage)921 angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
922                                                      const UtilsVk::BlitResolveParameters &params,
923                                                      vk::ImageHelper *srcImage)
924 {
925     vk::CommandBuffer *commandBuffer = nullptr;
926     ANGLE_TRY(
927         contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc, srcImage));
928 
929     VkImageResolve resolveRegion                = {};
930     resolveRegion.srcSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
931     resolveRegion.srcSubresource.mipLevel       = 0;
932     resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
933     resolveRegion.srcSubresource.layerCount     = 1;
934     resolveRegion.srcOffset.x                   = params.srcOffset[0];
935     resolveRegion.srcOffset.y                   = params.srcOffset[1];
936     resolveRegion.srcOffset.z                   = 0;
937     resolveRegion.dstSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
938     resolveRegion.dstSubresource.layerCount     = 1;
939     resolveRegion.dstOffset.x                   = params.destOffset[0];
940     resolveRegion.dstOffset.y                   = params.destOffset[1];
941     resolveRegion.dstOffset.z                   = 0;
942     resolveRegion.extent.width                  = params.srcExtents[0];
943     resolveRegion.extent.height                 = params.srcExtents[1];
944     resolveRegion.extent.depth                  = 1;
945 
946     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
947     {
948         RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
949         ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst,
950                                           &drawRenderTarget->getImage()));
951         ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
952 
953         resolveRegion.dstSubresource.mipLevel       = drawRenderTarget->getLevelIndex();
954         resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
955 
956         srcImage->resolve(&drawRenderTarget->getImage(), resolveRegion, commandBuffer);
957     }
958 
959     return angle::Result::Continue;
960 }
961 
checkStatus(const gl::Context * context) const962 bool FramebufferVk::checkStatus(const gl::Context *context) const
963 {
964     // if we have both a depth and stencil buffer, they must refer to the same object
965     // since we only support packed_depth_stencil and not separate depth and stencil
966     if (mState.hasSeparateDepthAndStencilAttachments())
967     {
968         return false;
969     }
970 
971     return true;
972 }
973 
invalidateImpl(ContextVk * contextVk,size_t count,const GLenum * attachments)974 angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
975                                             size_t count,
976                                             const GLenum *attachments)
977 {
978     ASSERT(contextVk->hasStartedRenderPass());
979 
980     gl::DrawBufferMask invalidateColorBuffers;
981     bool invalidateDepthBuffer   = false;
982     bool invalidateStencilBuffer = false;
983 
984     for (size_t i = 0; i < count; ++i)
985     {
986         const GLenum attachment = attachments[i];
987 
988         switch (attachment)
989         {
990             case GL_DEPTH:
991             case GL_DEPTH_ATTACHMENT:
992                 invalidateDepthBuffer = true;
993                 break;
994             case GL_STENCIL:
995             case GL_STENCIL_ATTACHMENT:
996                 invalidateStencilBuffer = true;
997                 break;
998             case GL_DEPTH_STENCIL_ATTACHMENT:
999                 invalidateDepthBuffer   = true;
1000                 invalidateStencilBuffer = true;
1001                 break;
1002             default:
1003                 ASSERT(
1004                     (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) ||
1005                     (attachment == GL_COLOR));
1006 
1007                 invalidateColorBuffers.set(
1008                     attachment == GL_COLOR ? 0u : (attachment - GL_COLOR_ATTACHMENT0));
1009         }
1010     }
1011 
1012     // Set the appropriate storeOp for attachments.
1013     size_t attachmentIndexVk = 0;
1014     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1015     {
1016         if (invalidateColorBuffers.test(colorIndexGL))
1017         {
1018             contextVk->getStartedRenderPassCommands().invalidateRenderPassColorAttachment(
1019                 attachmentIndexVk);
1020         }
1021         ++attachmentIndexVk;
1022     }
1023 
1024     RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil(true);
1025     if (depthStencilRenderTarget)
1026     {
1027         if (invalidateDepthBuffer)
1028         {
1029             contextVk->getStartedRenderPassCommands().invalidateRenderPassDepthAttachment(
1030                 attachmentIndexVk);
1031         }
1032 
1033         if (invalidateStencilBuffer)
1034         {
1035             contextVk->getStartedRenderPassCommands().invalidateRenderPassStencilAttachment(
1036                 attachmentIndexVk);
1037         }
1038     }
1039 
1040     // NOTE: Possible future optimization is to delay setting the storeOp and only do so if the
1041     // render pass is closed by itself before another draw call.  Otherwise, in a situation like
1042     // this:
1043     //
1044     //     draw()
1045     //     invalidate()
1046     //     draw()
1047     //
1048     // We would be discarding the attachments only to load them for the next draw (which is less
1049     // efficient than keeping the render pass open and not do the discard at all).  While dEQP tests
1050     // this pattern, this optimization may not be necessary if no application does this.  It is
1051     // expected that an application would invalidate() when it's done with the framebuffer, so the
1052     // render pass would have closed either way.
1053     ANGLE_TRY(contextVk->endRenderPass());
1054 
1055     return angle::Result::Continue;
1056 }
1057 
updateColorAttachment(const gl::Context * context,bool deferClears,uint32_t colorIndexGL)1058 angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context,
1059                                                    bool deferClears,
1060                                                    uint32_t colorIndexGL)
1061 {
1062     ContextVk *contextVk = vk::GetImpl(context);
1063 
1064     ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndexGL));
1065 
1066     // Update cached masks for masked clears.
1067     RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
1068     if (renderTarget)
1069     {
1070         const angle::Format &actualFormat = renderTarget->getImageFormat().actualImageFormat();
1071         updateActiveColorMasks(colorIndexGL, actualFormat.redBits > 0, actualFormat.greenBits > 0,
1072                                actualFormat.blueBits > 0, actualFormat.alphaBits > 0);
1073 
1074         const angle::Format &sourceFormat = renderTarget->getImageFormat().intendedFormat();
1075         mEmulatedAlphaAttachmentMask.set(colorIndexGL,
1076                                          sourceFormat.alphaBits == 0 && actualFormat.alphaBits > 0);
1077 
1078         contextVk->updateColorMask(context->getState().getBlendState());
1079 
1080         if (deferClears && mState.getEnabledDrawBuffers().test(colorIndexGL))
1081         {
1082             ANGLE_TRY(renderTarget->flushStagedUpdates(contextVk, &mDeferredClears, colorIndexGL));
1083         }
1084         else
1085         {
1086             ANGLE_TRY(renderTarget->flushStagedUpdates(contextVk, nullptr, 0));
1087         }
1088     }
1089     else
1090     {
1091         updateActiveColorMasks(colorIndexGL, false, false, false, false);
1092     }
1093 
1094     if (renderTarget && mState.getEnabledDrawBuffers()[colorIndexGL])
1095     {
1096         mCurrentFramebufferDesc.update(colorIndexGL, renderTarget->getAssignSerial(contextVk));
1097     }
1098     else
1099     {
1100         mCurrentFramebufferDesc.update(colorIndexGL, vk::kZeroAttachmentSerial);
1101     }
1102 
1103     return angle::Result::Continue;
1104 }
1105 
updateDepthStencilAttachment(const gl::Context * context,bool deferClears)1106 angle::Result FramebufferVk::updateDepthStencilAttachment(const gl::Context *context,
1107                                                           bool deferClears)
1108 {
1109     ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
1110 
1111     ContextVk *contextVk = vk::GetImpl(context);
1112     updateDepthStencilAttachmentSerial(contextVk);
1113 
1114     RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
1115     if (depthStencilRT)
1116     {
1117         if (deferClears)
1118         {
1119             ANGLE_TRY(depthStencilRT->flushStagedUpdates(contextVk, &mDeferredClears,
1120                                                          vk::kClearValueDepthIndex));
1121         }
1122         else
1123         {
1124             ANGLE_TRY(depthStencilRT->flushStagedUpdates(contextVk, nullptr, 0));
1125         }
1126     }
1127 
1128     return angle::Result::Continue;
1129 }
1130 
updateDepthStencilAttachmentSerial(ContextVk * contextVk)1131 void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
1132 {
1133     RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
1134 
1135     if (depthStencilRT != nullptr)
1136     {
1137         mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex,
1138                                        depthStencilRT->getAssignSerial(contextVk));
1139     }
1140     else
1141     {
1142         mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex,
1143                                        vk::kZeroAttachmentSerial);
1144     }
1145 }
1146 
syncState(const gl::Context * context,GLenum binding,const gl::Framebuffer::DirtyBits & dirtyBits)1147 angle::Result FramebufferVk::syncState(const gl::Context *context,
1148                                        GLenum binding,
1149                                        const gl::Framebuffer::DirtyBits &dirtyBits)
1150 {
1151     ContextVk *contextVk = vk::GetImpl(context);
1152 
1153     vk::FramebufferDesc priorFramebufferDesc = mCurrentFramebufferDesc;
1154 
1155     // Only defer clears for whole draw framebuffer ops. If the scissor test is on and the scissor
1156     // rect doesn't match the draw rect, forget it.
1157     gl::Rectangle renderArea          = getCompleteRenderArea();
1158     gl::Rectangle scissoredRenderArea = ClipRectToScissor(context->getState(), renderArea, false);
1159     bool deferClears = binding == GL_DRAW_FRAMEBUFFER && renderArea == scissoredRenderArea;
1160 
1161     // For any updated attachments we'll update their Serials below
1162     ASSERT(dirtyBits.any());
1163     for (size_t dirtyBit : dirtyBits)
1164     {
1165         switch (dirtyBit)
1166         {
1167             case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
1168             case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS:
1169             case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
1170             case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS:
1171                 ANGLE_TRY(updateDepthStencilAttachment(context, deferClears));
1172                 break;
1173             case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
1174                 ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
1175                 break;
1176             case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
1177                 // Force update of serial for enabled draw buffers
1178                 mCurrentFramebufferDesc.reset();
1179                 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1180                 {
1181                     mCurrentFramebufferDesc.update(
1182                         static_cast<uint32_t>(colorIndexGL),
1183                         mRenderTargetCache.getColors()[colorIndexGL]->getAssignSerial(contextVk));
1184                 }
1185                 updateDepthStencilAttachmentSerial(contextVk);
1186                 break;
1187             case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
1188             case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
1189             case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
1190             case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1191                 // Invalidate the cache. If we have performance critical code hitting this path we
1192                 // can add related data (such as width/height) to the cache
1193                 clearCache(contextVk);
1194                 break;
1195             default:
1196             {
1197                 static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
1198                 uint32_t colorIndexGL;
1199                 if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
1200                 {
1201                     colorIndexGL = static_cast<uint32_t>(
1202                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
1203                 }
1204                 else
1205                 {
1206                     ASSERT(dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 &&
1207                            dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX);
1208                     colorIndexGL = static_cast<uint32_t>(
1209                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
1210                 }
1211 
1212                 ANGLE_TRY(updateColorAttachment(context, deferClears, colorIndexGL));
1213                 break;
1214             }
1215         }
1216     }
1217 
1218     // In some cases we'll need to force a flush of deferred clears. When we're syncing the read
1219     // framebuffer we might not get a RenderPass. Also when there are masked out cleared color
1220     // channels.
1221     if (binding == GL_READ_FRAMEBUFFER && !mDeferredClears.empty())
1222     {
1223         ANGLE_TRY(flushDeferredClears(contextVk, scissoredRenderArea));
1224     }
1225 
1226     // No-op redundant changes to prevent closing the RenderPass.
1227     if (mCurrentFramebufferDesc == priorFramebufferDesc)
1228     {
1229         return angle::Result::Continue;
1230     }
1231 
1232     // The FBO's new attachment may have changed the renderable area
1233     const gl::State &glState = context->getState();
1234     ANGLE_TRY(contextVk->updateScissor(glState));
1235 
1236     mActiveColorComponents = gl_vk::GetColorComponentFlags(
1237         mActiveColorComponentMasksForClear[0].any(), mActiveColorComponentMasksForClear[1].any(),
1238         mActiveColorComponentMasksForClear[2].any(), mActiveColorComponentMasksForClear[3].any());
1239 
1240     ANGLE_TRY(contextVk->endRenderPass());
1241 
1242     // Notify the ContextVk to update the pipeline desc.
1243     updateRenderPassDesc();
1244 
1245     FramebufferVk *currentDrawFramebuffer = vk::GetImpl(context->getState().getDrawFramebuffer());
1246     if (currentDrawFramebuffer == this)
1247     {
1248         contextVk->onDrawFramebufferChange(this);
1249     }
1250     // Deactivate Framebuffer
1251     mFramebuffer = nullptr;
1252 
1253     return angle::Result::Continue;
1254 }
1255 
updateRenderPassDesc()1256 void FramebufferVk::updateRenderPassDesc()
1257 {
1258     mRenderPassDesc = {};
1259     mRenderPassDesc.setSamples(getSamples());
1260 
1261     const auto &colorRenderTargets              = mRenderTargetCache.getColors();
1262     const gl::DrawBufferMask enabledDrawBuffers = mState.getEnabledDrawBuffers();
1263     for (size_t colorIndexGL = 0; colorIndexGL < enabledDrawBuffers.size(); ++colorIndexGL)
1264     {
1265         if (enabledDrawBuffers[colorIndexGL])
1266         {
1267             RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1268             ASSERT(colorRenderTarget);
1269             mRenderPassDesc.packColorAttachment(
1270                 colorIndexGL, colorRenderTarget->getImage().getFormat().intendedFormatID);
1271         }
1272         else
1273         {
1274             mRenderPassDesc.packColorAttachmentGap(colorIndexGL);
1275         }
1276     }
1277 
1278     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
1279     if (depthStencilRenderTarget)
1280     {
1281         mRenderPassDesc.packDepthStencilAttachment(
1282             depthStencilRenderTarget->getImage().getFormat().intendedFormatID);
1283     }
1284 }
1285 
getFramebuffer(ContextVk * contextVk,vk::Framebuffer ** framebufferOut)1286 angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, vk::Framebuffer **framebufferOut)
1287 {
1288     // First return a presently valid Framebuffer
1289     if (mFramebuffer != nullptr)
1290     {
1291         *framebufferOut = &mFramebuffer->getFramebuffer();
1292         return angle::Result::Continue;
1293     }
1294     // No current FB, so now check for previously cached Framebuffer
1295     auto iter = mFramebufferCache.find(mCurrentFramebufferDesc);
1296     if (iter != mFramebufferCache.end())
1297     {
1298         if (contextVk->getRenderer()->getFeatures().enableFramebufferVkCache.enabled)
1299         {
1300             *framebufferOut = &iter->second.getFramebuffer();
1301             return angle::Result::Continue;
1302         }
1303         else
1304         {
1305             // When cache is off just release previous entry, it will be recreated below
1306             iter->second.release(contextVk);
1307         }
1308     }
1309     vk::RenderPass *compatibleRenderPass = nullptr;
1310     ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));
1311 
1312     // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
1313     if (mBackbuffer)
1314     {
1315         return mBackbuffer->getCurrentFramebuffer(contextVk, *compatibleRenderPass, framebufferOut);
1316     }
1317 
1318     // Gather VkImageViews over all FBO attachments, also size of attached region.
1319     std::vector<VkImageView> attachments;
1320     gl::Extents attachmentsSize;
1321 
1322     const auto &colorRenderTargets = mRenderTargetCache.getColors();
1323     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1324     {
1325         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1326         ASSERT(colorRenderTarget);
1327 
1328         const vk::ImageView *imageView = nullptr;
1329         ANGLE_TRY(colorRenderTarget->getImageView(contextVk, &imageView));
1330 
1331         attachments.push_back(imageView->getHandle());
1332 
1333         ASSERT(attachmentsSize.empty() || attachmentsSize == colorRenderTarget->getExtents());
1334         attachmentsSize = colorRenderTarget->getExtents();
1335     }
1336 
1337     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
1338     if (depthStencilRenderTarget)
1339     {
1340         const vk::ImageView *imageView = nullptr;
1341         ANGLE_TRY(depthStencilRenderTarget->getImageView(contextVk, &imageView));
1342 
1343         attachments.push_back(imageView->getHandle());
1344 
1345         ASSERT(attachmentsSize.empty() ||
1346                attachmentsSize == depthStencilRenderTarget->getExtents());
1347         attachmentsSize = depthStencilRenderTarget->getExtents();
1348     }
1349 
1350     if (attachmentsSize.empty())
1351     {
1352         // No attachments, so use the default values.
1353         attachmentsSize.height = mState.getDefaultHeight();
1354         attachmentsSize.width  = mState.getDefaultWidth();
1355         attachmentsSize.depth  = 0;
1356     }
1357     VkFramebufferCreateInfo framebufferInfo = {};
1358 
1359     framebufferInfo.sType           = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
1360     framebufferInfo.flags           = 0;
1361     framebufferInfo.renderPass      = compatibleRenderPass->getHandle();
1362     framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
1363     framebufferInfo.pAttachments    = attachments.data();
1364     framebufferInfo.width           = static_cast<uint32_t>(attachmentsSize.width);
1365     framebufferInfo.height          = static_cast<uint32_t>(attachmentsSize.height);
1366     framebufferInfo.layers          = 1;
1367 
1368     vk::FramebufferHelper newFramebuffer;
1369     ANGLE_TRY(newFramebuffer.init(contextVk, framebufferInfo));
1370 
1371     // Sanity check that our description matches our attachments. Can catch implementation bugs.
1372     ASSERT(static_cast<uint32_t>(attachments.size()) == mCurrentFramebufferDesc.attachmentCount());
1373 
1374     mFramebufferCache[mCurrentFramebufferDesc] = std::move(newFramebuffer);
1375     mFramebuffer                               = &mFramebufferCache[mCurrentFramebufferDesc];
1376     *framebufferOut                            = &mFramebuffer->getFramebuffer();
1377     return angle::Result::Continue;
1378 }
1379 
clearImmediatelyWithRenderPassOp(ContextVk * contextVk,const gl::Rectangle & clearArea,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)1380 angle::Result FramebufferVk::clearImmediatelyWithRenderPassOp(
1381     ContextVk *contextVk,
1382     const gl::Rectangle &clearArea,
1383     gl::DrawBufferMask clearColorBuffers,
1384     bool clearDepth,
1385     bool clearStencil,
1386     const VkClearColorValue &clearColorValue,
1387     const VkClearDepthStencilValue &clearDepthStencilValue)
1388 {
1389     for (size_t colorIndexGL : clearColorBuffers)
1390     {
1391         VkClearValue clearValue = getCorrectedColorClearValue(colorIndexGL, clearColorValue);
1392         mDeferredClears.store(static_cast<uint32_t>(colorIndexGL), VK_IMAGE_ASPECT_COLOR_BIT,
1393                               clearValue);
1394     }
1395 
1396     if (clearDepth)
1397     {
1398         VkClearValue clearValue;
1399         clearValue.depthStencil = clearDepthStencilValue;
1400         mDeferredClears.store(vk::kClearValueDepthIndex, VK_IMAGE_ASPECT_DEPTH_BIT, clearValue);
1401     }
1402 
1403     if (clearStencil)
1404     {
1405         VkClearValue clearValue;
1406         clearValue.depthStencil = clearDepthStencilValue;
1407         mDeferredClears.store(vk::kClearValueStencilIndex, VK_IMAGE_ASPECT_STENCIL_BIT, clearValue);
1408     }
1409 
1410     // Ensure the clear happens immediately.
1411     return flushDeferredClears(contextVk, clearArea);
1412 }
1413 
clearWithDraw(ContextVk * contextVk,const gl::Rectangle & clearArea,gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,VkColorComponentFlags colorMaskFlags,uint8_t stencilMask,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)1414 angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
1415                                            const gl::Rectangle &clearArea,
1416                                            gl::DrawBufferMask clearColorBuffers,
1417                                            bool clearDepth,
1418                                            bool clearStencil,
1419                                            VkColorComponentFlags colorMaskFlags,
1420                                            uint8_t stencilMask,
1421                                            const VkClearColorValue &clearColorValue,
1422                                            const VkClearDepthStencilValue &clearDepthStencilValue)
1423 {
1424     if (clearDepth)
1425     {
1426         VkClearValue clearValue;
1427         clearValue.depthStencil = clearDepthStencilValue;
1428         mDeferredClears.store(vk::kClearValueDepthIndex, VK_IMAGE_ASPECT_DEPTH_BIT, clearValue);
1429 
1430         // Scissored-only clears are handled in clearImmediatelyWithRenderPassOp.
1431         ASSERT(clearColorBuffers.any() || clearStencil);
1432     }
1433 
1434     UtilsVk::ClearFramebufferParameters params = {};
1435     params.clearArea                           = clearArea;
1436     params.colorClearValue                     = clearColorValue;
1437     params.stencilClearValue = static_cast<uint8_t>(clearDepthStencilValue.stencil);
1438     params.stencilMask       = stencilMask;
1439 
1440     params.clearColor   = true;
1441     params.clearStencil = clearStencil;
1442 
1443     const auto &colorRenderTargets = mRenderTargetCache.getColors();
1444     for (size_t colorIndexGL : clearColorBuffers)
1445     {
1446         const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1447         ASSERT(colorRenderTarget);
1448 
1449         params.colorFormat = &colorRenderTarget->getImage().getFormat().actualImageFormat();
1450         params.colorAttachmentIndexGL = static_cast<uint32_t>(colorIndexGL);
1451         params.colorMaskFlags         = colorMaskFlags;
1452         if (mEmulatedAlphaAttachmentMask[colorIndexGL])
1453         {
1454             params.colorMaskFlags &= ~VK_COLOR_COMPONENT_A_BIT;
1455         }
1456 
1457         ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
1458 
1459         // Clear stencil only once!
1460         params.clearStencil = false;
1461     }
1462 
1463     // If there was no color clear, clear stencil alone.
1464     if (params.clearStencil)
1465     {
1466         params.clearColor = false;
1467         ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
1468     }
1469 
1470     return angle::Result::Continue;
1471 }
1472 
getCorrectedColorClearValue(size_t colorIndexGL,const VkClearColorValue & clearColor) const1473 VkClearValue FramebufferVk::getCorrectedColorClearValue(size_t colorIndexGL,
1474                                                         const VkClearColorValue &clearColor) const
1475 {
1476     VkClearValue clearValue;
1477     clearValue.color = clearColor;
1478 
1479     if (!mEmulatedAlphaAttachmentMask[colorIndexGL])
1480     {
1481         return clearValue;
1482     }
1483 
1484     // If the render target doesn't have alpha, but its emulated format has it, clear the alpha
1485     // to 1.
1486     RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
1487     const vk::Format &format     = renderTarget->getImageFormat();
1488     if (format.vkFormatIsInt)
1489     {
1490         if (format.vkFormatIsUnsigned)
1491         {
1492             clearValue.color.uint32[3] = kEmulatedAlphaValue;
1493         }
1494         else
1495         {
1496             clearValue.color.int32[3] = kEmulatedAlphaValue;
1497         }
1498     }
1499     else
1500     {
1501         clearValue.color.float32[3] = kEmulatedAlphaValue;
1502     }
1503 
1504     return clearValue;
1505 }
1506 
clearWithRenderPassOp(gl::DrawBufferMask clearColorBuffers,bool clearDepth,bool clearStencil,const VkClearColorValue & clearColorValue,const VkClearDepthStencilValue & clearDepthStencilValue)1507 void FramebufferVk::clearWithRenderPassOp(gl::DrawBufferMask clearColorBuffers,
1508                                           bool clearDepth,
1509                                           bool clearStencil,
1510                                           const VkClearColorValue &clearColorValue,
1511                                           const VkClearDepthStencilValue &clearDepthStencilValue)
1512 {
1513     // Go through clearColorBuffers and set the appropriate loadOp and clear values.
1514     for (size_t colorIndexGL : clearColorBuffers)
1515     {
1516         ASSERT(mState.getEnabledDrawBuffers().test(colorIndexGL));
1517         RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
1518         VkClearValue clearValue      = getCorrectedColorClearValue(colorIndexGL, clearColorValue);
1519         gl::ImageIndex imageIndex    = renderTarget->getImageIndex();
1520         renderTarget->getImage().stageClear(imageIndex, VK_IMAGE_ASPECT_COLOR_BIT, clearValue);
1521     }
1522 
1523     // Set the appropriate loadOp and clear values for depth and stencil.
1524     VkImageAspectFlags dsAspectFlags = 0;
1525     if (clearDepth)
1526     {
1527         dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
1528     }
1529 
1530     if (clearStencil)
1531     {
1532         dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
1533     }
1534 
1535     if (dsAspectFlags)
1536     {
1537         RenderTargetVk *renderTarget = getDepthStencilRenderTarget();
1538         ASSERT(renderTarget);
1539 
1540         VkClearValue clearValue;
1541         clearValue.depthStencil = clearDepthStencilValue;
1542 
1543         gl::ImageIndex imageIndex = renderTarget->getImageIndex();
1544         renderTarget->getImage().stageClear(imageIndex, dsAspectFlags, clearValue);
1545     }
1546 }
1547 
getSamplePosition(const gl::Context * context,size_t index,GLfloat * xy) const1548 angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
1549                                                size_t index,
1550                                                GLfloat *xy) const
1551 {
1552     int sampleCount = getSamples();
1553     rx::GetSamplePosition(sampleCount, index, xy);
1554     return angle::Result::Continue;
1555 }
1556 
startNewRenderPass(ContextVk * contextVk,const gl::Rectangle & renderArea,vk::CommandBuffer ** commandBufferOut)1557 angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
1558                                                 const gl::Rectangle &renderArea,
1559                                                 vk::CommandBuffer **commandBufferOut)
1560 {
1561     vk::Framebuffer *framebuffer = nullptr;
1562     ANGLE_TRY(getFramebuffer(contextVk, &framebuffer));
1563 
1564     vk::AttachmentOpsArray renderPassAttachmentOps;
1565     vk::ClearValuesArray packedClearValues;
1566 
1567     ANGLE_TRY(contextVk->endRenderPass());
1568 
1569     // Initialize RenderPass info.
1570     const auto &colorRenderTargets  = mRenderTargetCache.getColors();
1571     uint32_t currentAttachmentCount = 0;
1572     for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
1573     {
1574         RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1575         ASSERT(colorRenderTarget);
1576 
1577         renderPassAttachmentOps.setLayouts(currentAttachmentCount, vk::ImageLayout::ColorAttachment,
1578                                            vk::ImageLayout::ColorAttachment);
1579 
1580         if (mDeferredClears.test(colorIndexGL))
1581         {
1582             renderPassAttachmentOps.setOps(currentAttachmentCount, VK_ATTACHMENT_LOAD_OP_CLEAR,
1583                                            VK_ATTACHMENT_STORE_OP_STORE);
1584             packedClearValues.store(currentAttachmentCount, VK_IMAGE_ASPECT_COLOR_BIT,
1585                                     mDeferredClears[colorIndexGL]);
1586             mDeferredClears.reset(colorIndexGL);
1587         }
1588         else
1589         {
1590             renderPassAttachmentOps.setOps(currentAttachmentCount, VK_ATTACHMENT_LOAD_OP_LOAD,
1591                                            VK_ATTACHMENT_STORE_OP_STORE);
1592             packedClearValues.store(currentAttachmentCount, VK_IMAGE_ASPECT_COLOR_BIT,
1593                                     kUninitializedClearValue);
1594         }
1595 
1596         ANGLE_TRY(colorRenderTarget->onColorDraw(contextVk));
1597 
1598         currentAttachmentCount++;
1599     }
1600 
1601     RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
1602     if (depthStencilRenderTarget)
1603     {
1604         VkAttachmentLoadOp depthLoadOp     = VK_ATTACHMENT_LOAD_OP_LOAD;
1605         VkAttachmentLoadOp stencilLoadOp   = VK_ATTACHMENT_LOAD_OP_LOAD;
1606         VkAttachmentStoreOp depthStoreOp   = VK_ATTACHMENT_STORE_OP_STORE;
1607         VkAttachmentStoreOp stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1608 
1609         if (!depthStencilRenderTarget->hasDefinedContent())
1610         {
1611             depthLoadOp   = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1612             stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1613         }
1614 
1615         renderPassAttachmentOps.setLayouts(currentAttachmentCount,
1616                                            vk::ImageLayout::DepthStencilAttachment,
1617                                            vk::ImageLayout::DepthStencilAttachment);
1618 
1619         if (mDeferredClears.testDepth() || mDeferredClears.testStencil())
1620         {
1621             VkClearValue clearValue;
1622 
1623             if (mDeferredClears.testDepth())
1624             {
1625                 depthLoadOp                   = VK_ATTACHMENT_LOAD_OP_CLEAR;
1626                 clearValue.depthStencil.depth = mDeferredClears.getDepthValue();
1627                 mDeferredClears.reset(vk::kClearValueDepthIndex);
1628             }
1629 
1630             if (mDeferredClears.testStencil())
1631             {
1632                 stencilLoadOp                   = VK_ATTACHMENT_LOAD_OP_CLEAR;
1633                 clearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
1634                 mDeferredClears.reset(vk::kClearValueStencilIndex);
1635             }
1636 
1637             // Note the aspect is only depth here. That's intentional.
1638             packedClearValues.store(currentAttachmentCount, VK_IMAGE_ASPECT_DEPTH_BIT, clearValue);
1639         }
1640         else
1641         {
1642             // Note the aspect is only depth here. That's intentional.
1643             packedClearValues.store(currentAttachmentCount, VK_IMAGE_ASPECT_DEPTH_BIT,
1644                                     kUninitializedClearValue);
1645         }
1646 
1647         const vk::Format &format = depthStencilRenderTarget->getImageFormat();
1648         if (format.hasEmulatedImageChannels())
1649         {
1650             // If the format we picked has stencil but user did not ask for it due to hardware
1651             // limitations, use DONT_CARE for load/store. The same logic for depth follows.
1652             if (format.intendedFormat().stencilBits == 0)
1653             {
1654                 stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1655                 stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1656             }
1657             if (format.intendedFormat().depthBits == 0)
1658             {
1659                 depthLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1660                 depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1661             }
1662         }
1663 
1664         renderPassAttachmentOps.setOps(currentAttachmentCount, depthLoadOp, depthStoreOp);
1665         renderPassAttachmentOps.setStencilOps(currentAttachmentCount, stencilLoadOp,
1666                                               stencilStoreOp);
1667 
1668         // This must be called after hasDefinedContent() since it will set content to valid. We are
1669         // tracking content valid very loosely here that as long as it is attached, it assumes will
1670         // have valid content. The only time it has undefined content is between swap and
1671         // startNewRenderPass
1672         ANGLE_TRY(depthStencilRenderTarget->onDepthStencilDraw(contextVk));
1673 
1674         currentAttachmentCount++;
1675     }
1676 
1677     return contextVk->flushAndBeginRenderPass(*framebuffer, renderArea, mRenderPassDesc,
1678                                               renderPassAttachmentOps, packedClearValues,
1679                                               commandBufferOut);
1680 }
1681 
updateActiveColorMasks(size_t colorIndexGL,bool r,bool g,bool b,bool a)1682 void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
1683 {
1684     mActiveColorComponentMasksForClear[0].set(colorIndexGL, r);
1685     mActiveColorComponentMasksForClear[1].set(colorIndexGL, g);
1686     mActiveColorComponentMasksForClear[2].set(colorIndexGL, b);
1687     mActiveColorComponentMasksForClear[3].set(colorIndexGL, a);
1688 }
1689 
getEmulatedAlphaAttachmentMask() const1690 const gl::DrawBufferMask &FramebufferVk::getEmulatedAlphaAttachmentMask() const
1691 {
1692     return mEmulatedAlphaAttachmentMask;
1693 }
1694 
readPixelsImpl(ContextVk * contextVk,const gl::Rectangle & area,const PackPixelsParams & packPixelsParams,VkImageAspectFlagBits copyAspectFlags,RenderTargetVk * renderTarget,void * pixels)1695 angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
1696                                             const gl::Rectangle &area,
1697                                             const PackPixelsParams &packPixelsParams,
1698                                             VkImageAspectFlagBits copyAspectFlags,
1699                                             RenderTargetVk *renderTarget,
1700                                             void *pixels)
1701 {
1702     ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
1703     uint32_t level = renderTarget->getLevelIndex();
1704     uint32_t layer = renderTarget->getLayerIndex();
1705     return renderTarget->getImage().readPixels(contextVk, area, packPixelsParams, copyAspectFlags,
1706                                                level, layer, pixels, &mReadPixelBuffer);
1707 }
1708 
getReadImageExtents() const1709 gl::Extents FramebufferVk::getReadImageExtents() const
1710 {
1711     RenderTargetVk *readRenderTarget = mRenderTargetCache.getColorRead(mState);
1712 
1713     ASSERT(readRenderTarget->getExtents().width == mState.getDimensions().width);
1714     ASSERT(readRenderTarget->getExtents().height == mState.getDimensions().height);
1715 
1716     return readRenderTarget->getExtents();
1717 }
1718 
getCompleteRenderArea() const1719 gl::Rectangle FramebufferVk::getCompleteRenderArea() const
1720 {
1721     const gl::Box &dimensions = mState.getDimensions();
1722     return gl::Rectangle(0, 0, dimensions.width, dimensions.height);
1723 }
1724 
getScissoredRenderArea(ContextVk * contextVk) const1725 gl::Rectangle FramebufferVk::getScissoredRenderArea(ContextVk *contextVk) const
1726 {
1727     const gl::Rectangle renderArea = getCompleteRenderArea();
1728     bool invertViewport            = contextVk->isViewportFlipEnabledForDrawFBO();
1729     gl::Rectangle scissoredArea    = ClipRectToScissor(contextVk->getState(), renderArea, false);
1730     gl::Rectangle rotatedScissoredArea;
1731     RotateRectangle(contextVk->getRotationDrawFramebuffer(), invertViewport, renderArea.width,
1732                     renderArea.height, scissoredArea, &rotatedScissoredArea);
1733     return rotatedScissoredArea;
1734 }
1735 
getFirstRenderTarget() const1736 RenderTargetVk *FramebufferVk::getFirstRenderTarget() const
1737 {
1738     for (auto *renderTarget : mRenderTargetCache.getColors())
1739     {
1740         if (renderTarget)
1741         {
1742             return renderTarget;
1743         }
1744     }
1745 
1746     return getDepthStencilRenderTarget();
1747 }
1748 
getSamples() const1749 GLint FramebufferVk::getSamples() const
1750 {
1751     RenderTargetVk *firstRT = getFirstRenderTarget();
1752     return firstRT ? firstRT->getImage().getSamples() : 0;
1753 }
1754 
flushDeferredClears(ContextVk * contextVk,const gl::Rectangle & renderArea)1755 angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk,
1756                                                  const gl::Rectangle &renderArea)
1757 {
1758     if (mDeferredClears.empty())
1759         return angle::Result::Continue;
1760 
1761     return contextVk->startRenderPass(renderArea, nullptr);
1762 }
1763 }  // namespace rx
1764