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, ¶ms,
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 ¶ms,
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