blob: b0b6645791aeeea4a06e5dbe33004562a46ce6ba [file] [log] [blame]
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001//
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
Jamie Madill7b57b9d2017-01-13 09:33:38 -050012#include <vulkan/vulkan.h>
Jamie Madill231c7f52017-04-26 13:45:37 -040013#include <array>
Jamie Madill7b57b9d2017-01-13 09:33:38 -050014
Jamie Madill9e54b5a2016-05-25 12:57:39 -040015#include "common/debug.h"
Jamie Madillc564c072017-06-01 12:45:42 -040016#include "libANGLE/Context.h"
17#include "libANGLE/Display.h"
Jamie Madill7b57b9d2017-01-13 09:33:38 -050018#include "libANGLE/formatutils.h"
19#include "libANGLE/renderer/renderer_utils.h"
Jamie Madill1f46bc12018-02-20 16:09:43 -050020#include "libANGLE/renderer/vulkan/CommandGraph.h"
Jamie Madill7b57b9d2017-01-13 09:33:38 -050021#include "libANGLE/renderer/vulkan/ContextVk.h"
Jamie Madill5deea722017-02-16 10:44:46 -050022#include "libANGLE/renderer/vulkan/DisplayVk.h"
Jamie Madill7b57b9d2017-01-13 09:33:38 -050023#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
24#include "libANGLE/renderer/vulkan/RendererVk.h"
25#include "libANGLE/renderer/vulkan/SurfaceVk.h"
Jamie Madill3c424b42018-01-19 12:35:09 -050026#include "libANGLE/renderer/vulkan/vk_format_utils.h"
Jamie Madill3ea463b2019-06-19 14:21:33 -040027#include "libANGLE/trace.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040028
29namespace rx
30{
31
Jamie Madill7b57b9d2017-01-13 09:33:38 -050032namespace
33{
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -040034// The value to assign an alpha channel that's emulated. The type is unsigned int, though it will
35// automatically convert to the actual data type.
36constexpr unsigned int kEmulatedAlphaValue = 1;
37
Luc Ferron534b00d2018-05-18 08:16:53 -040038constexpr size_t kMinReadPixelsBufferSize = 128000;
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -040039// Clear values are only used when loadOp=Clear is set in clearWithRenderPassOp. When starting a
40// new render pass, the clear value is set to an unlikely value (bright pink) to stand out better
41// in case of a bug.
42constexpr VkClearValue kUninitializedClearValue = {{{0.95, 0.05, 0.95, 0.95}}};
Luc Ferron534b00d2018-05-18 08:16:53 -040043
Jamie Madill66546be2018-03-08 09:47:20 -050044const gl::InternalFormat &GetReadAttachmentInfo(const gl::Context *context,
45 RenderTargetVk *renderTarget)
Jamie Madill7b57b9d2017-01-13 09:33:38 -050046{
Jamie Madillbc543422018-03-30 10:43:19 -040047 GLenum implFormat =
Jamie Madill0631e192019-04-18 16:09:12 -040048 renderTarget->getImageFormat().imageFormat().fboImplementationInternalFormat;
Jamie Madill66546be2018-03-08 09:47:20 -050049 return gl::GetSizedInternalFormatInfo(implFormat);
Jamie Madill7b57b9d2017-01-13 09:33:38 -050050}
Luc Ferron26581112018-06-21 09:43:08 -040051
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -040052bool HasSrcBlitFeature(RendererVk *renderer, RenderTargetVk *srcRenderTarget)
Luc Ferron26581112018-06-21 09:43:08 -040053{
Jamie Madill0631e192019-04-18 16:09:12 -040054 const VkFormat srcFormat = srcRenderTarget->getImageFormat().vkImageFormat;
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -040055 return renderer->hasImageFormatFeatureBits(srcFormat, VK_FORMAT_FEATURE_BLIT_SRC_BIT);
56}
Luc Ferron26581112018-06-21 09:43:08 -040057
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -040058bool HasDstBlitFeature(RendererVk *renderer, RenderTargetVk *dstRenderTarget)
59{
60 const VkFormat dstFormat = dstRenderTarget->getImageFormat().vkImageFormat;
61 return renderer->hasImageFormatFeatureBits(dstFormat, VK_FORMAT_FEATURE_BLIT_DST_BIT);
62}
63
64// Returns false if destination has any channel the source doesn't. This means that channel was
65// emulated and using the Vulkan blit command would overwrite that emulated channel.
66bool areSrcAndDstColorChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
67 RenderTargetVk *dstRenderTarget)
68{
69 const angle::Format &srcFormat = srcRenderTarget->getImageFormat().angleFormat();
70 const angle::Format &dstFormat = dstRenderTarget->getImageFormat().angleFormat();
71
72 // Luminance/alpha formats are not renderable, so they can't have ended up in a framebuffer to
73 // participate in a blit.
74 ASSERT(!dstFormat.isLUMA() && !srcFormat.isLUMA());
75
76 // All color formats have the red channel.
77 ASSERT(dstFormat.redBits > 0 && srcFormat.redBits > 0);
78
79 return (dstFormat.greenBits > 0 || srcFormat.greenBits == 0) &&
80 (dstFormat.blueBits > 0 || srcFormat.blueBits == 0) &&
81 (dstFormat.alphaBits > 0 || srcFormat.alphaBits == 0);
82}
83
84bool areSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
85 RenderTargetVk *dstRenderTarget)
86{
87 const angle::Format &srcFormat = srcRenderTarget->getImageFormat().angleFormat();
88 const angle::Format &dstFormat = dstRenderTarget->getImageFormat().angleFormat();
89
90 return (dstFormat.depthBits > 0 || srcFormat.depthBits == 0) &&
91 (dstFormat.stencilBits > 0 || srcFormat.stencilBits == 0);
Luc Ferron26581112018-06-21 09:43:08 -040092}
Jamie Madillb436aac2018-07-18 17:23:48 -040093
94// Special rules apply to VkBufferImageCopy with depth/stencil. The components are tightly packed
95// into a depth or stencil section of the destination buffer. See the spec:
96// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkBufferImageCopy.html
97const angle::Format &GetDepthStencilImageToBufferFormat(const angle::Format &imageFormat,
98 VkImageAspectFlagBits copyAspect)
99{
100 if (copyAspect == VK_IMAGE_ASPECT_STENCIL_BIT)
101 {
102 ASSERT(imageFormat.id == angle::FormatID::D24_UNORM_S8_UINT ||
103 imageFormat.id == angle::FormatID::D32_FLOAT_S8X24_UINT ||
104 imageFormat.id == angle::FormatID::S8_UINT);
105 return angle::Format::Get(angle::FormatID::S8_UINT);
106 }
107
108 ASSERT(copyAspect == VK_IMAGE_ASPECT_DEPTH_BIT);
109
110 switch (imageFormat.id)
111 {
112 case angle::FormatID::D16_UNORM:
113 return imageFormat;
114 case angle::FormatID::D24_UNORM_X8_UINT:
115 return imageFormat;
116 case angle::FormatID::D24_UNORM_S8_UINT:
117 return angle::Format::Get(angle::FormatID::D24_UNORM_X8_UINT);
118 case angle::FormatID::D32_FLOAT:
119 return imageFormat;
120 case angle::FormatID::D32_FLOAT_S8X24_UINT:
121 return angle::Format::Get(angle::FormatID::D32_FLOAT);
122 default:
123 UNREACHABLE();
124 return imageFormat;
125 }
126}
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400127
128void SetEmulatedAlphaValue(const vk::Format &format, VkClearColorValue *value)
129{
130 if (format.vkFormatIsInt)
131 {
132 if (format.vkFormatIsUnsigned)
133 {
134 value->uint32[3] = kEmulatedAlphaValue;
135 }
136 else
137 {
138 value->int32[3] = kEmulatedAlphaValue;
139 }
140 }
141 else
142 {
143 value->float32[3] = kEmulatedAlphaValue;
144 }
145}
Jamie Madillbcf467f2018-05-23 09:46:00 -0400146} // anonymous namespace
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500147
148// static
Jamie Madill639bc902018-07-18 17:08:27 -0400149FramebufferVk *FramebufferVk::CreateUserFBO(RendererVk *renderer, const gl::FramebufferState &state)
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500150{
Jamie Madill639bc902018-07-18 17:08:27 -0400151 return new FramebufferVk(renderer, state, nullptr);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500152}
153
154// static
Jamie Madill639bc902018-07-18 17:08:27 -0400155FramebufferVk *FramebufferVk::CreateDefaultFBO(RendererVk *renderer,
156 const gl::FramebufferState &state,
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500157 WindowSurfaceVk *backbuffer)
158{
Jamie Madill639bc902018-07-18 17:08:27 -0400159 return new FramebufferVk(renderer, state, backbuffer);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500160}
161
Jamie Madill639bc902018-07-18 17:08:27 -0400162FramebufferVk::FramebufferVk(RendererVk *renderer,
163 const gl::FramebufferState &state,
164 WindowSurfaceVk *backbuffer)
Jamie Madill7f2520f2019-06-26 11:18:33 -0400165 : FramebufferImpl(state), mBackbuffer(backbuffer), mActiveColorComponents(0)
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500166{
Jamie Madill7f2520f2019-06-26 11:18:33 -0400167 mReadPixelBuffer.init(renderer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 4, kMinReadPixelsBufferSize,
168 true);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500169}
170
Jamie Madill58675012018-05-22 14:54:07 -0400171FramebufferVk::~FramebufferVk() = default;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400172
Jamie Madillc564c072017-06-01 12:45:42 -0400173void FramebufferVk::destroy(const gl::Context *context)
Jamie Madill5deea722017-02-16 10:44:46 -0500174{
Luc Ferron534b00d2018-05-18 08:16:53 -0400175 ContextVk *contextVk = vk::GetImpl(context);
Geoff Langee244c72019-05-06 10:30:18 -0400176 mFramebuffer.release(contextVk);
Luc Ferron534b00d2018-05-18 08:16:53 -0400177
Geoff Langee244c72019-05-06 10:30:18 -0400178 mReadPixelBuffer.release(contextVk);
Jamie Madill5deea722017-02-16 10:44:46 -0500179}
180
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400181angle::Result FramebufferVk::discard(const gl::Context *context,
182 size_t count,
183 const GLenum *attachments)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400184{
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400185 ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
Jamie Madill7c985f52018-11-29 18:16:17 -0500186 return angle::Result::Stop;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400187}
188
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400189angle::Result FramebufferVk::invalidate(const gl::Context *context,
190 size_t count,
191 const GLenum *attachments)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400192{
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400193 ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
Jamie Madill7c985f52018-11-29 18:16:17 -0500194 return angle::Result::Stop;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400195}
196
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400197angle::Result FramebufferVk::invalidateSub(const gl::Context *context,
198 size_t count,
199 const GLenum *attachments,
200 const gl::Rectangle &area)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400201{
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400202 ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
Jamie Madill7c985f52018-11-29 18:16:17 -0500203 return angle::Result::Stop;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400204}
205
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400206angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400207{
Jamie Madill0cec82a2018-03-14 09:21:07 -0400208 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500209
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400210 bool clearColor = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT));
211 bool clearDepth = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT));
212 bool clearStencil = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_STENCIL_BUFFER_BIT));
213 gl::DrawBufferMask clearColorBuffers;
214 if (clearColor)
215 {
216 clearColorBuffers = mState.getEnabledDrawBuffers();
217 }
218
219 const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
220 const VkClearDepthStencilValue &clearDepthStencilValue =
221 contextVk->getClearDepthStencilValue().depthStencil;
222
223 return clearImpl(context, clearColorBuffers, clearDepth, clearStencil, clearColorValue,
224 clearDepthStencilValue);
225}
226
227angle::Result FramebufferVk::clearImpl(const gl::Context *context,
228 gl::DrawBufferMask clearColorBuffers,
229 bool clearDepth,
230 bool clearStencil,
231 const VkClearColorValue &clearColorValue,
232 const VkClearDepthStencilValue &clearDepthStencilValue)
233{
234 ContextVk *contextVk = vk::GetImpl(context);
235
Shahbaz Youssefi127990f2019-04-04 13:52:04 -0400236 const gl::Rectangle scissoredRenderArea = getScissoredRenderArea(contextVk);
237
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400238 // Discard clear altogether if scissor has 0 width or height.
Shahbaz Youssefi127990f2019-04-04 13:52:04 -0400239 if (scissoredRenderArea.width == 0 || scissoredRenderArea.height == 0)
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400240 {
241 return angle::Result::Continue;
242 }
243
Geoff Langee244c72019-05-06 10:30:18 -0400244 mFramebuffer.updateQueueSerial(contextVk->getCurrentQueueSerial());
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400245
246 // This function assumes that only enabled attachments are asked to be cleared.
247 ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400248
Shahbaz Youssefiedef8952019-04-04 10:03:09 -0400249 // Adjust clear behavior based on whether the respective attachments are present; if asked to
250 // clear a non-existent attachment, don't attempt to clear it.
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400251
252 VkColorComponentFlags colorMaskFlags = contextVk->getClearColorMask();
253 bool clearColor = clearColorBuffers.any();
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400254
Jamie Madill0cec82a2018-03-14 09:21:07 -0400255 const gl::FramebufferAttachment *depthAttachment = mState.getDepthAttachment();
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400256 clearDepth = clearDepth && depthAttachment;
Jamie Madill0cec82a2018-03-14 09:21:07 -0400257 ASSERT(!clearDepth || depthAttachment->isAttached());
258
259 const gl::FramebufferAttachment *stencilAttachment = mState.getStencilAttachment();
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400260 clearStencil = clearStencil && stencilAttachment;
Jamie Madill0cec82a2018-03-14 09:21:07 -0400261 ASSERT(!clearStencil || stencilAttachment->isAttached());
262
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400263 uint8_t stencilMask =
264 static_cast<uint8_t>(contextVk->getState().getDepthStencilState().stencilWritemask);
265
266 // The front-end should ensure we don't attempt to clear color if all channels are masked.
267 ASSERT(!clearColor || colorMaskFlags != 0);
268 // The front-end should ensure we don't attempt to clear depth if depth write is disabled.
269 ASSERT(!clearDepth || contextVk->getState().getDepthStencilState().depthMask);
270 // The front-end should ensure we don't attempt to clear stencil if all bits are masked.
271 ASSERT(!clearStencil || stencilMask != 0);
272
273 // If there is nothing to clear, return right away (for example, if asked to clear depth, but
274 // there is no depth attachment).
Shahbaz Youssefi02a579e2019-03-27 14:21:20 -0400275 if (!clearColor && !clearDepth && !clearStencil)
276 {
277 return angle::Result::Continue;
278 }
279
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400280 VkClearDepthStencilValue modifiedDepthStencilValue = clearDepthStencilValue;
Shahbaz Youssefid856ca42018-10-31 16:55:12 -0400281
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400282 // We can use render pass load ops if clearing depth, unmasked color or unmasked stencil. If
283 // there's a depth mask, depth clearing is already disabled.
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -0400284 bool maskedClearColor =
285 clearColor && (mActiveColorComponents & colorMaskFlags) != mActiveColorComponents;
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400286 bool maskedClearStencil = stencilMask != 0xFF;
287
288 bool clearColorWithRenderPassLoadOp = clearColor && !maskedClearColor;
289 bool clearStencilWithRenderPassLoadOp = clearStencil && !maskedClearStencil;
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400290
291 // At least one of color, depth or stencil should be clearable with render pass loadOp for us
292 // to use this clear path.
Shahbaz Youssefif1153b02019-03-27 11:22:54 -0400293 bool clearAnyWithRenderPassLoadOp =
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400294 clearColorWithRenderPassLoadOp || clearDepth || clearStencilWithRenderPassLoadOp;
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -0400295
Shahbaz Youssefi127990f2019-04-04 13:52:04 -0400296 if (clearAnyWithRenderPassLoadOp)
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -0400297 {
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400298 // Clearing color is indicated by the set bits in this mask. If not clearing colors with
299 // render pass loadOp, the default value of all-zeros means the clear is not done in
Shahbaz Youssefi127990f2019-04-04 13:52:04 -0400300 // clearWithRenderPassOp below. In that case, only clear depth/stencil with render pass
301 // loadOp.
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400302 gl::DrawBufferMask clearBuffersWithRenderPassLoadOp;
303 if (clearColorWithRenderPassLoadOp)
304 {
305 clearBuffersWithRenderPassLoadOp = clearColorBuffers;
306 }
Shahbaz Youssefi127990f2019-04-04 13:52:04 -0400307 ANGLE_TRY(clearWithRenderPassOp(
308 contextVk, scissoredRenderArea, clearBuffersWithRenderPassLoadOp, clearDepth,
309 clearStencilWithRenderPassLoadOp, clearColorValue, modifiedDepthStencilValue));
Shahbaz Youssefif1153b02019-03-27 11:22:54 -0400310
Shahbaz Youssefi27f115a2019-04-01 10:33:21 -0400311 // On some hardware, having inline commands at this point results in corrupted output. In
312 // that case, end the render pass immediately. http://anglebug.com/2361
Jonah Ryan-Davis776694c2019-05-08 10:28:55 -0400313 if (contextVk->getRenderer()->getFeatures().restartRenderPassAfterLoadOpClear.enabled)
Shahbaz Youssefi27f115a2019-04-01 10:33:21 -0400314 {
Geoff Langee244c72019-05-06 10:30:18 -0400315 mFramebuffer.finishCurrentCommands(contextVk);
Shahbaz Youssefi27f115a2019-04-01 10:33:21 -0400316 }
317
Shahbaz Youssefif1153b02019-03-27 11:22:54 -0400318 // Fallback to other methods for whatever isn't cleared here.
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400319 clearDepth = false;
Shahbaz Youssefif1153b02019-03-27 11:22:54 -0400320 if (clearColorWithRenderPassLoadOp)
321 {
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400322 clearColorBuffers.reset();
Shahbaz Youssefif1153b02019-03-27 11:22:54 -0400323 clearColor = false;
324 }
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400325 if (clearStencilWithRenderPassLoadOp)
326 {
327 clearStencil = false;
328 }
Shahbaz Youssefif1153b02019-03-27 11:22:54 -0400329
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400330 // If nothing left to clear, early out.
331 if (!clearColor && !clearStencil)
Shahbaz Youssefif1153b02019-03-27 11:22:54 -0400332 {
333 return angle::Result::Continue;
334 }
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -0400335 }
336
Shahbaz Youssefi2249d4a2019-04-05 16:48:55 -0400337 // Note: depth clear is always done through render pass loadOp.
Shahbaz Youssefi127990f2019-04-04 13:52:04 -0400338 ASSERT(clearDepth == false);
339
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -0400340 // The most costly clear mode is when we need to mask out specific color channels or stencil
Shahbaz Youssefi2249d4a2019-04-05 16:48:55 -0400341 // bits. This can only be done with a draw call.
342 return clearWithDraw(contextVk, scissoredRenderArea, clearColorBuffers, clearStencil,
343 colorMaskFlags, stencilMask, clearColorValue,
344 static_cast<uint8_t>(modifiedDepthStencilValue.stencil));
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400345}
346
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400347angle::Result FramebufferVk::clearBufferfv(const gl::Context *context,
348 GLenum buffer,
349 GLint drawbuffer,
350 const GLfloat *values)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400351{
Shahbaz Youssefiedef8952019-04-04 10:03:09 -0400352 VkClearValue clearValue = {};
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400353
354 bool clearDepth = false;
355 gl::DrawBufferMask clearColorBuffers;
356
357 if (buffer == GL_DEPTH)
358 {
359 clearDepth = true;
360 clearValue.depthStencil.depth = values[0];
361 }
362 else
363 {
364 clearColorBuffers.set(drawbuffer);
365 clearValue.color.float32[0] = values[0];
366 clearValue.color.float32[1] = values[1];
367 clearValue.color.float32[2] = values[2];
368 clearValue.color.float32[3] = values[3];
369 }
370
371 return clearImpl(context, clearColorBuffers, clearDepth, false, clearValue.color,
372 clearValue.depthStencil);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400373}
374
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400375angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context,
376 GLenum buffer,
377 GLint drawbuffer,
378 const GLuint *values)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400379{
Shahbaz Youssefiedef8952019-04-04 10:03:09 -0400380 VkClearValue clearValue = {};
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400381
382 gl::DrawBufferMask clearColorBuffers;
383 clearColorBuffers.set(drawbuffer);
384
385 clearValue.color.uint32[0] = values[0];
386 clearValue.color.uint32[1] = values[1];
387 clearValue.color.uint32[2] = values[2];
388 clearValue.color.uint32[3] = values[3];
389
390 return clearImpl(context, clearColorBuffers, false, false, clearValue.color,
391 clearValue.depthStencil);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400392}
393
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400394angle::Result FramebufferVk::clearBufferiv(const gl::Context *context,
395 GLenum buffer,
396 GLint drawbuffer,
397 const GLint *values)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400398{
Shahbaz Youssefiedef8952019-04-04 10:03:09 -0400399 VkClearValue clearValue = {};
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400400
401 bool clearStencil = false;
402 gl::DrawBufferMask clearColorBuffers;
403
404 if (buffer == GL_STENCIL)
405 {
406 clearStencil = true;
407 clearValue.depthStencil.stencil =
408 gl::clamp(values[0], 0, std::numeric_limits<uint8_t>::max());
409 }
410 else
411 {
412 clearColorBuffers.set(drawbuffer);
413 clearValue.color.int32[0] = values[0];
414 clearValue.color.int32[1] = values[1];
415 clearValue.color.int32[2] = values[2];
416 clearValue.color.int32[3] = values[3];
417 }
418
419 return clearImpl(context, clearColorBuffers, false, clearStencil, clearValue.color,
420 clearValue.depthStencil);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400421}
422
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400423angle::Result FramebufferVk::clearBufferfi(const gl::Context *context,
424 GLenum buffer,
425 GLint drawbuffer,
426 GLfloat depth,
427 GLint stencil)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400428{
Shahbaz Youssefiedef8952019-04-04 10:03:09 -0400429 VkClearValue clearValue = {};
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -0400430
431 clearValue.depthStencil.depth = depth;
432 clearValue.depthStencil.stencil = gl::clamp(stencil, 0, std::numeric_limits<uint8_t>::max());
433
434 return clearImpl(context, gl::DrawBufferMask(), true, true, clearValue.color,
435 clearValue.depthStencil);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400436}
437
Jamie Madill4928b7c2017-06-20 12:57:39 -0400438GLenum FramebufferVk::getImplementationColorReadFormat(const gl::Context *context) const
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400439{
Jamie Madill66546be2018-03-08 09:47:20 -0500440 return GetReadAttachmentInfo(context, mRenderTargetCache.getColorRead(mState)).format;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400441}
442
Jamie Madill4928b7c2017-06-20 12:57:39 -0400443GLenum FramebufferVk::getImplementationColorReadType(const gl::Context *context) const
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400444{
Jamie Madill66546be2018-03-08 09:47:20 -0500445 return GetReadAttachmentInfo(context, mRenderTargetCache.getColorRead(mState)).type;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400446}
447
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400448angle::Result FramebufferVk::readPixels(const gl::Context *context,
449 const gl::Rectangle &area,
450 GLenum format,
451 GLenum type,
452 void *pixels)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400453{
Luc Ferrona1c72422018-05-14 15:58:28 -0400454 // Clip read area to framebuffer.
455 const gl::Extents &fbSize = getState().getReadAttachment()->getSize();
456 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
Luc Ferronbf6dc372018-06-28 15:24:19 -0400457 ContextVk *contextVk = vk::GetImpl(context);
Luc Ferronbf6dc372018-06-28 15:24:19 -0400458
Luc Ferrona1c72422018-05-14 15:58:28 -0400459 gl::Rectangle clippedArea;
460 if (!ClipRectangle(area, fbRect, &clippedArea))
461 {
462 // nothing to read
Jamie Madill7c985f52018-11-29 18:16:17 -0500463 return angle::Result::Continue;
Luc Ferrona1c72422018-05-14 15:58:28 -0400464 }
Luc Ferronbf6dc372018-06-28 15:24:19 -0400465 gl::Rectangle flippedArea = clippedArea;
Geoff Lange076a232018-07-16 15:34:05 -0400466 if (contextVk->isViewportFlipEnabledForReadFBO())
Luc Ferronbf6dc372018-06-28 15:24:19 -0400467 {
468 flippedArea.y = fbRect.height - flippedArea.y - flippedArea.height;
469 }
Luc Ferrona1c72422018-05-14 15:58:28 -0400470
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500471 const gl::State &glState = context->getState();
Frank Henigman1ffad842018-09-24 23:40:45 -0400472 const gl::PixelPackState &packState = glState.getPackState();
Luc Ferronbf6dc372018-06-28 15:24:19 -0400473
Luc Ferrona1c72422018-05-14 15:58:28 -0400474 const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
475
476 GLuint outputPitch = 0;
Jamie Madillabfbc0f2018-10-09 12:48:52 -0400477 ANGLE_VK_CHECK_MATH(contextVk,
478 sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment,
479 packState.rowLength, &outputPitch));
Luc Ferrona1c72422018-05-14 15:58:28 -0400480 GLuint outputSkipBytes = 0;
Jamie Madillabfbc0f2018-10-09 12:48:52 -0400481 ANGLE_VK_CHECK_MATH(contextVk, sizedFormatInfo.computeSkipBytes(type, outputPitch, 0, packState,
482 false, &outputSkipBytes));
Luc Ferrona1c72422018-05-14 15:58:28 -0400483
484 outputSkipBytes += (clippedArea.x - area.x) * sizedFormatInfo.pixelBytes +
485 (clippedArea.y - area.y) * outputPitch;
Luc Ferron60284222018-03-20 16:01:44 -0400486
Jamie Madilldb9c69e2018-07-18 17:23:47 -0400487 const angle::Format &angleFormat = GetFormatFromFormatType(format, type);
488
Frank Henigman1ffad842018-09-24 23:40:45 -0400489 PackPixelsParams params(flippedArea, angleFormat, outputPitch, packState.reverseRowOrder,
Jamie Madilldb9c69e2018-07-18 17:23:47 -0400490 glState.getTargetBuffer(gl::BufferBinding::PixelPack), 0);
Frank Henigman1ffad842018-09-24 23:40:45 -0400491 if (contextVk->isViewportFlipEnabledForReadFBO())
492 {
493 params.reverseRowOrder = !params.reverseRowOrder;
494 }
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500495
Jamie Madill21061022018-07-12 23:56:30 -0400496 ANGLE_TRY(readPixelsImpl(contextVk, flippedArea, params, VK_IMAGE_ASPECT_COLOR_BIT,
Luc Ferron1617e692018-07-11 11:08:19 -0400497 getColorReadRenderTarget(),
Rafael Cintron05a449a2018-06-20 18:08:04 -0700498 static_cast<uint8_t *>(pixels) + outputSkipBytes));
Geoff Langee244c72019-05-06 10:30:18 -0400499 mReadPixelBuffer.releaseRetainedBuffers(contextVk);
Jamie Madill7c985f52018-11-29 18:16:17 -0500500 return angle::Result::Continue;
Luc Ferron018709f2018-05-10 13:53:11 -0400501}
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500502
Luc Ferron26581112018-06-21 09:43:08 -0400503RenderTargetVk *FramebufferVk::getDepthStencilRenderTarget() const
504{
505 return mRenderTargetCache.getDepthStencil();
506}
507
Jamie Madill58675012018-05-22 14:54:07 -0400508RenderTargetVk *FramebufferVk::getColorReadRenderTarget() const
Luc Ferron018709f2018-05-10 13:53:11 -0400509{
510 RenderTargetVk *renderTarget = mRenderTargetCache.getColorRead(mState);
Jamie Madillbcf467f2018-05-23 09:46:00 -0400511 ASSERT(renderTarget && renderTarget->getImage().valid());
Luc Ferron018709f2018-05-10 13:53:11 -0400512 return renderTarget;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400513}
514
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400515angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400516 const gl::Rectangle &sourceArea,
517 const gl::Rectangle &destArea,
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400518 RenderTargetVk *readRenderTarget,
519 RenderTargetVk *drawRenderTarget,
520 GLenum filter,
521 bool colorBlit,
522 bool depthBlit,
523 bool stencilBlit,
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400524 bool flipX,
525 bool flipY)
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400526{
527 // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
528 // it should never be the case that both color and depth/stencil need to be blitted at
529 // at the same time.
530 ASSERT(colorBlit != (depthBlit || stencilBlit));
531
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400532 vk::ImageHelper *srcImage = &readRenderTarget->getImage();
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400533 vk::ImageHelper *dstImage = drawRenderTarget->getImageForWrite(&mFramebuffer);
534
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400535 VkImageAspectFlags imageAspectMask = srcImage->getAspectFlags();
536 VkImageAspectFlags blitAspectMask = imageAspectMask;
537
538 // Remove depth or stencil aspects if they are not requested to be blitted.
539 if (!depthBlit)
540 {
541 blitAspectMask &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
542 }
543 if (!stencilBlit)
544 {
545 blitAspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
546 }
547
548 if (srcImage->isLayoutChangeNecessary(vk::ImageLayout::TransferSrc))
549 {
550 vk::CommandBuffer *srcLayoutChange;
551 ANGLE_TRY(srcImage->recordCommands(contextVk, &srcLayoutChange));
552 srcImage->changeLayout(imageAspectMask, vk::ImageLayout::TransferSrc, srcLayoutChange);
553 }
554
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400555 vk::CommandBuffer *commandBuffer = nullptr;
556 ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
557
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400558 srcImage->addReadDependency(&mFramebuffer);
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400559
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400560 VkImageBlit blit = {};
561 blit.srcSubresource.aspectMask = blitAspectMask;
562 blit.srcSubresource.mipLevel = readRenderTarget->getLevelIndex();
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400563 blit.srcSubresource.baseArrayLayer = readRenderTarget->getLayerIndex();
564 blit.srcSubresource.layerCount = 1;
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400565 blit.srcOffsets[0] = {sourceArea.x0(), sourceArea.y0(), 0};
566 blit.srcOffsets[1] = {sourceArea.x1(), sourceArea.y1(), 1};
567 blit.dstSubresource.aspectMask = blitAspectMask;
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400568 blit.dstSubresource.mipLevel = drawRenderTarget->getLevelIndex();
569 blit.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
570 blit.dstSubresource.layerCount = 1;
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400571 blit.dstOffsets[0] = {destArea.x0(), destArea.y0(), 0};
572 blit.dstOffsets[1] = {destArea.x1(), destArea.y1(), 1};
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400573
574 // Requirement of the copyImageToBuffer, the dst image must be in
575 // VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout.
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400576 dstImage->changeLayout(imageAspectMask, vk::ImageLayout::TransferDst, commandBuffer);
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400577
578 commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
579 dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
580 gl_vk::GetFilter(filter));
581
582 return angle::Result::Continue;
583}
584
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400585angle::Result FramebufferVk::blit(const gl::Context *context,
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400586 const gl::Rectangle &sourceAreaIn,
587 const gl::Rectangle &destAreaIn,
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400588 GLbitfield mask,
589 GLenum filter)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400590{
Luc Ferron26581112018-06-21 09:43:08 -0400591 ContextVk *contextVk = vk::GetImpl(context);
592 RendererVk *renderer = contextVk->getRenderer();
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400593 UtilsVk &utilsVk = contextVk->getUtils();
Luc Ferron26581112018-06-21 09:43:08 -0400594
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400595 const gl::State &glState = contextVk->getState();
596 const gl::Framebuffer *srcFramebuffer = glState.getReadFramebuffer();
597
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400598 const bool blitColorBuffer = (mask & GL_COLOR_BUFFER_BIT) != 0;
599 const bool blitDepthBuffer = (mask & GL_DEPTH_BUFFER_BIT) != 0;
600 const bool blitStencilBuffer = (mask & GL_STENCIL_BUFFER_BIT) != 0;
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400601
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400602 const bool isResolve = srcFramebuffer->getCachedSamples(context) > 1;
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400603
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400604 FramebufferVk *srcFramebufferVk = vk::GetImpl(srcFramebuffer);
605 const bool srcFramebufferFlippedY = contextVk->isViewportFlipEnabledForReadFBO();
606 const bool destFramebufferFlippedY = contextVk->isViewportFlipEnabledForDrawFBO();
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400607
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400608 gl::Rectangle sourceArea = sourceAreaIn;
609 gl::Rectangle destArea = destAreaIn;
610
611 // Note: GLES (all 3.x versions) require source and dest area to be identical when
612 // resolving.
613 ASSERT(!isResolve ||
614 (sourceArea.x == destArea.x && sourceArea.y == destArea.y &&
615 sourceArea.width == destArea.width && sourceArea.height == destArea.height));
616
617 const gl::Rectangle srcFramebufferDimensions =
618 srcFramebufferVk->mState.getDimensions().toRect();
619
620 // If the destination is flipped in either direction, we will flip the source instead so that
621 // the destination area is always unflipped.
622 sourceArea = sourceArea.flip(destArea.isReversedX(), destArea.isReversedY());
623 destArea = destArea.removeReversal();
624
625 // Calculate the stretch factor prior to any clipping, as it needs to remain constant.
626 const float stretch[2] = {
627 std::abs(sourceArea.width / static_cast<float>(destArea.width)),
628 std::abs(sourceArea.height / static_cast<float>(destArea.height)),
629 };
630
631 // First, clip the source area to framebuffer. That requires transforming the dest area to
632 // match the clipped source.
633 gl::Rectangle absSourceArea = sourceArea.removeReversal();
634 gl::Rectangle clippedSourceArea;
635 if (!gl::ClipRectangle(srcFramebufferDimensions, absSourceArea, &clippedSourceArea))
636 {
637 return angle::Result::Continue;
638 }
639
640 // Resize the destination area based on the new size of source. Note again that stretch is
641 // calculated as SrcDimension/DestDimension.
642 gl::Rectangle srcClippedDestArea;
643 if (isResolve)
644 {
645 // Source and dest areas are identical in resolve.
646 srcClippedDestArea = clippedSourceArea;
647 }
648 else if (clippedSourceArea == absSourceArea)
649 {
650 // If there was no clipping, keep dest area as is.
651 srcClippedDestArea = destArea;
652 }
653 else
654 {
655 // Shift dest area's x0,y0,x1,y1 by as much as the source area's got shifted (taking
656 // stretching into account)
657 float x0Shift = std::round((clippedSourceArea.x - absSourceArea.x) / stretch[0]);
658 float y0Shift = std::round((clippedSourceArea.y - absSourceArea.y) / stretch[1]);
659 float x1Shift = std::round((absSourceArea.x1() - clippedSourceArea.x1()) / stretch[0]);
660 float y1Shift = std::round((absSourceArea.y1() - clippedSourceArea.y1()) / stretch[1]);
661
662 // If the source area was reversed in any direction, the shift should be applied in the
663 // opposite direction as well.
664 if (sourceArea.isReversedX())
665 {
666 std::swap(x0Shift, x1Shift);
667 }
668
669 if (sourceArea.isReversedY())
670 {
671 std::swap(y0Shift, y1Shift);
672 }
673
674 srcClippedDestArea.x = destArea.x0() + static_cast<int>(x0Shift);
675 srcClippedDestArea.y = destArea.y0() + static_cast<int>(y0Shift);
676 int x1 = destArea.x1() - static_cast<int>(x1Shift);
677 int y1 = destArea.y1() - static_cast<int>(y1Shift);
678
679 srcClippedDestArea.width = x1 - srcClippedDestArea.x;
680 srcClippedDestArea.height = y1 - srcClippedDestArea.y;
681 }
682
683 // If framebuffers are flipped in Y, flip the source and dest area (which define the
684 // transformation regardless of clipping), as well as the blit area (which is the clipped
685 // dest area).
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400686 if (srcFramebufferFlippedY)
687 {
688 sourceArea.y = srcFramebufferDimensions.height - sourceArea.y;
689 sourceArea.height = -sourceArea.height;
690 }
691 if (destFramebufferFlippedY)
692 {
693 destArea.y = mState.getDimensions().height - destArea.y;
694 destArea.height = -destArea.height;
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400695
696 srcClippedDestArea.y =
697 mState.getDimensions().height - srcClippedDestArea.y - srcClippedDestArea.height;
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400698 }
699
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400700 const bool flipX = sourceArea.isReversedX() != destArea.isReversedX();
701 const bool flipY = sourceArea.isReversedY() != destArea.isReversedY();
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400702
703 // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve.
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400704 ASSERT(!isResolve ||
705 (flipX == false && flipY == (srcFramebufferFlippedY != destFramebufferFlippedY)));
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400706
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400707 // Again, transfer the destination flip to source, so dest is unflipped. Note that destArea
708 // was not reversed until the final possible Y-flip.
709 ASSERT(!destArea.isReversedX());
710 sourceArea = sourceArea.flip(false, destArea.isReversedY());
711 destArea = destArea.removeReversal();
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400712
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400713 // Clip the destination area to the framebuffer size and scissor. Note that we don't care
714 // about the source area anymore. The offset translation is done based on the original source
715 // and destination rectangles. The stretch factor is already calculated as well.
716 gl::Rectangle blitArea;
717 if (!gl::ClipRectangle(getScissoredRenderArea(contextVk), srcClippedDestArea, &blitArea))
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400718 {
719 return angle::Result::Continue;
720 }
721
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400722 bool noClip = blitArea == destArea && stretch[0] == 1.0f && stretch[1] == 1.0f;
723 bool noFlip = !flipX && !flipY;
724 bool disableFlippingBlitWithCommand =
725 contextVk->getRenderer()->getFeatures().disableFlippingBlitWithCommand.enabled;
726
Shahbaz Youssefide70a712019-06-03 17:05:16 -0400727 UtilsVk::BlitResolveParameters params;
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400728 params.srcOffset[0] = sourceArea.x;
729 params.srcOffset[1] = sourceArea.y;
730 params.destOffset[0] = destArea.x;
731 params.destOffset[1] = destArea.y;
732 params.stretch[0] = stretch[0];
733 params.stretch[1] = stretch[1];
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400734 params.srcExtents[0] = srcFramebufferDimensions.width;
735 params.srcExtents[1] = srcFramebufferDimensions.height;
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400736 params.blitArea = blitArea;
737 params.linear = filter == GL_LINEAR;
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400738 params.flipX = flipX;
739 params.flipY = flipY;
740
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400741 if (blitColorBuffer)
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400742 {
743 RenderTargetVk *readRenderTarget = srcFramebufferVk->getColorReadRenderTarget();
744 params.srcLayer = readRenderTarget->getLayerIndex();
745
746 // Multisampled images are not allowed to have mips.
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400747 ASSERT(!isResolve || readRenderTarget->getLevelIndex() == 0);
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400748
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400749 // If there was no clipping and the format capabilities allow us, use Vulkan's builtin blit.
750 // The reason clipping is prohibited in this path is that due to rounding errors, it would
751 // be hard to guarantee the image stretching remains perfect. That also allows us not to
752 // have to transform back the dest clipping to source.
753 //
754 // For simplicity, we either blit all render targets with a Vulkan command, or none.
755 bool canBlitWithCommand = !isResolve && noClip &&
756 (noFlip || !disableFlippingBlitWithCommand) &&
757 HasSrcBlitFeature(renderer, readRenderTarget);
758 bool areChannelsBlitCompatible = true;
759 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
760 {
761 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
762 canBlitWithCommand =
763 canBlitWithCommand && HasDstBlitFeature(renderer, drawRenderTarget);
764 areChannelsBlitCompatible =
765 areChannelsBlitCompatible &&
766 areSrcAndDstColorChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
767 }
768
769 if (canBlitWithCommand && areChannelsBlitCompatible)
770 {
771 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
772 {
773 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
774 ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
775 drawRenderTarget, filter, true, false, false, flipX,
776 flipY));
777 }
778 }
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400779 // If we're not flipping, use Vulkan's builtin resolve.
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400780 else if (isResolve && !flipX && !flipY && areChannelsBlitCompatible)
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400781 {
782 ANGLE_TRY(resolveColorWithCommand(contextVk, params, &readRenderTarget->getImage()));
783 }
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400784 // Otherwise use a shader to do blit or resolve.
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400785 else
786 {
Shahbaz Youssefide70a712019-06-03 17:05:16 -0400787 ANGLE_TRY(utilsVk.colorBlitResolve(contextVk, this, &readRenderTarget->getImage(),
788 readRenderTarget->getFetchImageView(), params));
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400789 }
790 }
791
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400792 if (blitDepthBuffer || blitStencilBuffer)
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400793 {
794 RenderTargetVk *readRenderTarget = srcFramebufferVk->getDepthStencilRenderTarget();
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400795 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getDepthStencil();
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400796 params.srcLayer = readRenderTarget->getLayerIndex();
797
798 // Multisampled images are not allowed to have mips.
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400799 ASSERT(!isResolve || readRenderTarget->getLevelIndex() == 0);
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400800
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400801 // Similarly, only blit if there's been no clipping.
802 bool canBlitWithCommand = !isResolve && noClip &&
803 (noFlip || !disableFlippingBlitWithCommand) &&
804 HasSrcBlitFeature(renderer, readRenderTarget) &&
805 HasDstBlitFeature(renderer, drawRenderTarget);
806 bool areChannelsBlitCompatible =
807 areSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400808
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400809 if (canBlitWithCommand && areChannelsBlitCompatible)
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400810 {
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400811 ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
812 drawRenderTarget, filter, false, blitDepthBuffer,
813 blitStencilBuffer, flipX, flipY));
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400814 }
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400815 else
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400816 {
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400817 // Create depth- and stencil-only views for reading.
818 vk::Scoped<vk::ImageView> depthView(contextVk->getDevice());
819 vk::Scoped<vk::ImageView> stencilView(contextVk->getDevice());
820
821 vk::ImageHelper *depthStencilImage = &readRenderTarget->getImage();
822 uint32_t levelIndex = readRenderTarget->getLevelIndex();
823 uint32_t layerIndex = readRenderTarget->getLayerIndex();
824 gl::TextureType textureType = vk::Get2DTextureType(depthStencilImage->getLayerCount(),
825 depthStencilImage->getSamples());
826
827 if (blitDepthBuffer)
828 {
829 ANGLE_TRY(depthStencilImage->initLayerImageView(
830 contextVk, textureType, VK_IMAGE_ASPECT_DEPTH_BIT, gl::SwizzleState(),
831 &depthView.get(), levelIndex, 1, layerIndex, 1));
832 }
833
834 if (blitStencilBuffer)
835 {
836 ANGLE_TRY(depthStencilImage->initLayerImageView(
837 contextVk, textureType, VK_IMAGE_ASPECT_STENCIL_BIT, gl::SwizzleState(),
838 &stencilView.get(), levelIndex, 1, layerIndex, 1));
839 }
840
841 // If shader stencil export is not possible, defer stencil blit/stencil to another pass.
842 bool hasShaderStencilExport =
843 contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled;
844
845 // Blit depth. If shader stencil export is present, blit stencil as well.
846 if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport))
847 {
848 vk::ImageView *depth = blitDepthBuffer ? &depthView.get() : nullptr;
849 vk::ImageView *stencil =
850 blitStencilBuffer && hasShaderStencilExport ? &stencilView.get() : nullptr;
851
852 ANGLE_TRY(utilsVk.depthStencilBlitResolve(contextVk, this, depthStencilImage, depth,
853 stencil, params));
854 }
855
856 // If shader stencil export is not present, blit stencil through a different path.
857 if (blitStencilBuffer && !hasShaderStencilExport)
858 {
859 ANGLE_TRY(utilsVk.stencilBlitResolveNoShaderExport(
860 contextVk, this, depthStencilImage, &stencilView.get(), params));
861 }
862
863 vk::ImageView depthViewObject = depthView.release();
864 vk::ImageView stencilViewObject = stencilView.release();
865
866 contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &depthViewObject);
867 contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &stencilViewObject);
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400868 }
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400869 }
870
871 return angle::Result::Continue;
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400872} // namespace rx
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400873
874angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
Shahbaz Youssefide70a712019-06-03 17:05:16 -0400875 const UtilsVk::BlitResolveParameters &params,
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400876 vk::ImageHelper *srcImage)
877{
878 if (srcImage->isLayoutChangeNecessary(vk::ImageLayout::TransferSrc))
879 {
880 vk::CommandBuffer *srcLayoutChange;
881 ANGLE_TRY(srcImage->recordCommands(contextVk, &srcLayoutChange));
882 srcImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc,
883 srcLayoutChange);
884 }
Jamie Madill16c20142018-10-01 13:58:19 -0400885
Shahbaz Youssefi2660b502019-03-21 12:08:40 -0400886 vk::CommandBuffer *commandBuffer = nullptr;
Jamie Madill16c20142018-10-01 13:58:19 -0400887 ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
888
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400889 // Source's layout change should happen before rendering
890 srcImage->addReadDependency(&mFramebuffer);
Luc Ferron26581112018-06-21 09:43:08 -0400891
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400892 VkImageResolve resolveRegion = {};
893 resolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
894 resolveRegion.srcSubresource.mipLevel = 0;
895 resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
896 resolveRegion.srcSubresource.layerCount = 1;
897 resolveRegion.srcOffset.x = params.srcOffset[0];
898 resolveRegion.srcOffset.y = params.srcOffset[1];
899 resolveRegion.srcOffset.z = 0;
900 resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
901 resolveRegion.dstSubresource.layerCount = 1;
902 resolveRegion.dstOffset.x = params.destOffset[0];
903 resolveRegion.dstOffset.y = params.destOffset[1];
904 resolveRegion.dstOffset.z = 0;
905 resolveRegion.extent.width = params.srcExtents[0];
906 resolveRegion.extent.height = params.srcExtents[1];
907 resolveRegion.extent.depth = 1;
Jamie Madilld754eb52018-07-19 14:55:03 -0400908
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400909 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
Luc Ferron82eda932018-07-09 15:10:22 -0400910 {
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400911 RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
Shahbaz Youssefib407e1a2019-06-03 17:15:51 -0400912 vk::ImageHelper *drawImage = drawRenderTarget->getImageForWrite(&mFramebuffer);
913 drawImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst,
914 commandBuffer);
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -0400915
916 resolveRegion.dstSubresource.mipLevel = drawRenderTarget->getLevelIndex();
917 resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
918
919 srcImage->resolve(&drawRenderTarget->getImage(), resolveRegion, commandBuffer);
Luc Ferron82eda932018-07-09 15:10:22 -0400920 }
921
Jamie Madill7c985f52018-11-29 18:16:17 -0500922 return angle::Result::Continue;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400923}
924
Kenneth Russellce8602a2017-10-03 18:23:08 -0700925bool FramebufferVk::checkStatus(const gl::Context *context) const
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400926{
Luc Ferron5bdf8bd2018-06-20 09:51:37 -0400927 // if we have both a depth and stencil buffer, they must refer to the same object
928 // since we only support packed_depth_stencil and not separate depth and stencil
929 if (mState.hasSeparateDepthAndStencilAttachments())
930 {
931 return false;
932 }
933
Jamie Madillb79e7bb2017-10-24 13:55:50 -0400934 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400935}
936
Jamie Madill67220092019-05-20 11:12:53 -0400937angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context, size_t colorIndexGL)
938{
939 ContextVk *contextVk = vk::GetImpl(context);
940
941 ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndexGL));
942
943 // Update cached masks for masked clears.
944 RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
945 if (renderTarget)
946 {
947 const angle::Format &emulatedFormat = renderTarget->getImageFormat().imageFormat();
948 updateActiveColorMasks(colorIndexGL, emulatedFormat.redBits > 0,
949 emulatedFormat.greenBits > 0, emulatedFormat.blueBits > 0,
950 emulatedFormat.alphaBits > 0);
951
952 const angle::Format &sourceFormat = renderTarget->getImageFormat().angleFormat();
953 mEmulatedAlphaAttachmentMask.set(
954 colorIndexGL, sourceFormat.alphaBits == 0 && emulatedFormat.alphaBits > 0);
955
956 contextVk->updateColorMask(context->getState().getBlendState());
957 }
958 else
959 {
960 updateActiveColorMasks(colorIndexGL, false, false, false, false);
961 }
962
963 return angle::Result::Continue;
964}
965
Jamie Madill6f755b22018-10-09 12:48:54 -0400966angle::Result FramebufferVk::syncState(const gl::Context *context,
967 const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400968{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400969 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400970
971 ASSERT(dirtyBits.any());
Jamie Madill57d9cbb2018-04-27 11:45:04 -0400972 for (size_t dirtyBit : dirtyBits)
973 {
974 switch (dirtyBit)
975 {
976 case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
977 case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
978 ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
979 break;
Jamie Madill67220092019-05-20 11:12:53 -0400980 case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS:
981 case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS:
982 ANGLE_TRY(mRenderTargetCache.getDepthStencil()->flushStagedUpdates(contextVk));
983 break;
Jamie Madill57d9cbb2018-04-27 11:45:04 -0400984 case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
985 case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
986 case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
987 case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
988 case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
989 case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
990 break;
991 default:
992 {
Jamie Madill67220092019-05-20 11:12:53 -0400993 static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
994 if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
Jamie Madill9aef3672018-04-27 11:45:06 -0400995 {
Jamie Madill67220092019-05-20 11:12:53 -0400996 size_t colorIndexGL = static_cast<size_t>(
997 dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
998 ANGLE_TRY(updateColorAttachment(context, colorIndexGL));
Jamie Madill9aef3672018-04-27 11:45:06 -0400999 }
1000 else
1001 {
Jamie Madill67220092019-05-20 11:12:53 -04001002 ASSERT(dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 &&
1003 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX);
1004 size_t colorIndexGL = static_cast<size_t>(
1005 dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
1006 ANGLE_TRY(mRenderTargetCache.getColors()[colorIndexGL]->flushStagedUpdates(
1007 contextVk));
Jamie Madill9aef3672018-04-27 11:45:06 -04001008 }
Jamie Madill57d9cbb2018-04-27 11:45:04 -04001009 break;
1010 }
1011 }
1012 }
Jamie Madill66546be2018-03-08 09:47:20 -05001013
Jamie Madill9aef3672018-04-27 11:45:06 -04001014 mActiveColorComponents = gl_vk::GetColorComponentFlags(
Luc Ferron5fd36932018-06-19 14:55:50 -04001015 mActiveColorComponentMasksForClear[0].any(), mActiveColorComponentMasksForClear[1].any(),
1016 mActiveColorComponentMasksForClear[2].any(), mActiveColorComponentMasksForClear[3].any());
Jamie Madill9aef3672018-04-27 11:45:06 -04001017
Geoff Langee244c72019-05-06 10:30:18 -04001018 mFramebuffer.release(contextVk);
Jamie Madill49ac74b2017-12-21 14:42:33 -05001019
Jamie Madill316c6062018-05-29 10:49:45 -04001020 // Will freeze the current set of dependencies on this FBO. The next time we render we will
Jamie Madilla5e06072018-05-18 14:36:05 -04001021 // create a new entry in the command graph.
Geoff Langee244c72019-05-06 10:30:18 -04001022 mFramebuffer.finishCurrentCommands(contextVk);
Jamie Madill72106562017-03-24 14:18:50 -04001023
Jamie Madilldbc605c2019-01-04 16:39:14 -05001024 // Notify the ContextVk to update the pipeline desc.
1025 updateRenderPassDesc();
1026 contextVk->onFramebufferChange(mRenderPassDesc);
Jamie Madill19fa1c62018-03-08 09:47:21 -05001027
Jamie Madill7c985f52018-11-29 18:16:17 -05001028 return angle::Result::Continue;
Jamie Madillab9f9c32017-01-17 17:47:34 -05001029}
1030
Jamie Madilldbc605c2019-01-04 16:39:14 -05001031void FramebufferVk::updateRenderPassDesc()
Jamie Madillab9f9c32017-01-17 17:47:34 -05001032{
Jamie Madilldbc605c2019-01-04 16:39:14 -05001033 mRenderPassDesc = {};
1034 mRenderPassDesc.setSamples(getSamples());
Jamie Madillab9f9c32017-01-17 17:47:34 -05001035
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001036 const auto &colorRenderTargets = mRenderTargetCache.getColors();
1037 const gl::DrawBufferMask enabledDrawBuffers = mState.getEnabledDrawBuffers();
1038 for (size_t colorIndexGL = 0; colorIndexGL < enabledDrawBuffers.size(); ++colorIndexGL)
Jamie Madillab9f9c32017-01-17 17:47:34 -05001039 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001040 if (enabledDrawBuffers[colorIndexGL])
1041 {
1042 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
1043 ASSERT(colorRenderTarget);
1044 mRenderPassDesc.packColorAttachment(
1045 colorIndexGL, colorRenderTarget->getImage().getFormat().angleFormatID);
1046 }
1047 else
1048 {
1049 mRenderPassDesc.packColorAttachmentGap(colorIndexGL);
1050 }
Jamie Madillab9f9c32017-01-17 17:47:34 -05001051 }
1052
Jamie Madill66546be2018-03-08 09:47:20 -05001053 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
1054 if (depthStencilRenderTarget)
Jamie Madillab9f9c32017-01-17 17:47:34 -05001055 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001056 mRenderPassDesc.packDepthStencilAttachment(
1057 depthStencilRenderTarget->getImage().getFormat().angleFormatID);
Jamie Madillab9f9c32017-01-17 17:47:34 -05001058 }
Jamie Madillab9f9c32017-01-17 17:47:34 -05001059}
1060
Jamie Madill21061022018-07-12 23:56:30 -04001061angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, vk::Framebuffer **framebufferOut)
Jamie Madillab9f9c32017-01-17 17:47:34 -05001062{
1063 // If we've already created our cached Framebuffer, return it.
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001064 if (mFramebuffer.valid())
Jamie Madillab9f9c32017-01-17 17:47:34 -05001065 {
Jamie Madille8dd0792018-09-27 15:04:27 -04001066 *framebufferOut = &mFramebuffer.getFramebuffer();
Jamie Madill7c985f52018-11-29 18:16:17 -05001067 return angle::Result::Continue;
Jamie Madillab9f9c32017-01-17 17:47:34 -05001068 }
1069
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001070 vk::RenderPass *compatibleRenderPass = nullptr;
Geoff Langee244c72019-05-06 10:30:18 -04001071 ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));
Jamie Madillab9f9c32017-01-17 17:47:34 -05001072
1073 // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
1074 if (mBackbuffer)
1075 {
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001076 return mBackbuffer->getCurrentFramebuffer(contextVk, *compatibleRenderPass, framebufferOut);
Jamie Madillab9f9c32017-01-17 17:47:34 -05001077 }
1078
1079 // Gather VkImageViews over all FBO attachments, also size of attached region.
1080 std::vector<VkImageView> attachments;
1081 gl::Extents attachmentsSize;
1082
Jamie Madill66546be2018-03-08 09:47:20 -05001083 const auto &colorRenderTargets = mRenderTargetCache.getColors();
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001084 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
Jamie Madillab9f9c32017-01-17 17:47:34 -05001085 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001086 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
Jamie Madill66546be2018-03-08 09:47:20 -05001087 ASSERT(colorRenderTarget);
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +01001088 attachments.push_back(colorRenderTarget->getDrawImageView()->getHandle());
Jamie Madillab9f9c32017-01-17 17:47:34 -05001089
Shahbaz Youssefi68549402019-03-25 23:30:49 -04001090 ASSERT(attachmentsSize.empty() || attachmentsSize == colorRenderTarget->getExtents());
1091 attachmentsSize = colorRenderTarget->getExtents();
Jamie Madillab9f9c32017-01-17 17:47:34 -05001092 }
1093
Jamie Madill66546be2018-03-08 09:47:20 -05001094 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
1095 if (depthStencilRenderTarget)
Jamie Madillab9f9c32017-01-17 17:47:34 -05001096 {
Shahbaz Youssefif83a28a2018-12-09 03:48:34 +01001097 attachments.push_back(depthStencilRenderTarget->getDrawImageView()->getHandle());
Jamie Madillab9f9c32017-01-17 17:47:34 -05001098
Jamie Madillbc543422018-03-30 10:43:19 -04001099 ASSERT(attachmentsSize.empty() ||
Shahbaz Youssefi68549402019-03-25 23:30:49 -04001100 attachmentsSize == depthStencilRenderTarget->getExtents());
1101 attachmentsSize = depthStencilRenderTarget->getExtents();
Jamie Madillab9f9c32017-01-17 17:47:34 -05001102 }
1103
Shahbaz Youssefi06270c92018-10-03 17:00:25 -04001104 VkFramebufferCreateInfo framebufferInfo = {};
Jamie Madillab9f9c32017-01-17 17:47:34 -05001105
1106 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
Jamie Madillab9f9c32017-01-17 17:47:34 -05001107 framebufferInfo.flags = 0;
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001108 framebufferInfo.renderPass = compatibleRenderPass->getHandle();
Jamie Madillab9f9c32017-01-17 17:47:34 -05001109 framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
1110 framebufferInfo.pAttachments = attachments.data();
1111 framebufferInfo.width = static_cast<uint32_t>(attachmentsSize.width);
1112 framebufferInfo.height = static_cast<uint32_t>(attachmentsSize.height);
1113 framebufferInfo.layers = 1;
1114
Jamie Madill21061022018-07-12 23:56:30 -04001115 ANGLE_TRY(mFramebuffer.init(contextVk, framebufferInfo));
Jamie Madill5deea722017-02-16 10:44:46 -05001116
Jamie Madille8dd0792018-09-27 15:04:27 -04001117 *framebufferOut = &mFramebuffer.getFramebuffer();
Jamie Madill7c985f52018-11-29 18:16:17 -05001118 return angle::Result::Continue;
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001119}
1120
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001121angle::Result FramebufferVk::clearWithRenderPassOp(
1122 ContextVk *contextVk,
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001123 const gl::Rectangle &clearArea,
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001124 gl::DrawBufferMask clearColorBuffers,
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001125 bool clearDepth,
1126 bool clearStencil,
1127 const VkClearColorValue &clearColorValue,
1128 const VkClearDepthStencilValue &clearDepthStencilValue)
1129{
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001130 // Start a new render pass if:
1131 //
1132 // - no render pass has started,
1133 // - there is a render pass started but it contains commands; we cannot modify its ops, so new
1134 // render pass is needed,
1135 // - the current render area doesn't match the clear area. We need the render area to be
1136 // exactly as specified by the scissor for the loadOp to clear only that area. See
1137 // onScissorChange for more information.
1138
1139 if (!mFramebuffer.valid() || !mFramebuffer.renderPassStartedButEmpty() ||
1140 mFramebuffer.getRenderPassRenderArea() != clearArea)
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001141 {
1142 vk::CommandBuffer *commandBuffer;
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001143 ANGLE_TRY(startNewRenderPass(contextVk, clearArea, &commandBuffer));
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001144 }
1145
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001146 size_t attachmentIndexVk = 0;
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001147
1148 // Go through clearColorBuffers and set the appropriate loadOp and clear values.
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001149 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001150 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001151 if (clearColorBuffers.test(colorIndexGL))
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001152 {
1153 RenderTargetVk *renderTarget = getColorReadRenderTarget();
1154
1155 // If the render target doesn't have alpha, but its emulated format has it, clear the
1156 // alpha to 1.
1157 VkClearColorValue value = clearColorValue;
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001158 if (mEmulatedAlphaAttachmentMask[colorIndexGL])
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001159 {
1160 SetEmulatedAlphaValue(renderTarget->getImageFormat(), &value);
1161 }
1162
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001163 mFramebuffer.clearRenderPassColorAttachment(attachmentIndexVk, value);
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001164 }
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001165 ++attachmentIndexVk;
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001166 }
1167
1168 // Set the appropriate loadOp and clear values for depth and stencil.
1169 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
1170 if (depthStencilRenderTarget)
1171 {
1172 if (clearDepth)
1173 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001174 mFramebuffer.clearRenderPassDepthAttachment(attachmentIndexVk,
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001175 clearDepthStencilValue.depth);
1176 }
1177
1178 if (clearStencil)
1179 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001180 mFramebuffer.clearRenderPassStencilAttachment(attachmentIndexVk,
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001181 clearDepthStencilValue.stencil);
1182 }
1183 }
1184
1185 return angle::Result::Continue;
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001186}
1187
Jamie Madill21061022018-07-12 23:56:30 -04001188angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001189 const gl::Rectangle &clearArea,
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001190 gl::DrawBufferMask clearColorBuffers,
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001191 bool clearStencil,
1192 VkColorComponentFlags colorMaskFlags,
1193 uint8_t stencilMask,
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001194 const VkClearColorValue &clearColorValue,
Shahbaz Youssefi2249d4a2019-04-05 16:48:55 -04001195 uint8_t clearStencilValue)
Jamie Madill9aef3672018-04-27 11:45:06 -04001196{
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001197 UtilsVk::ClearFramebufferParameters params = {};
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001198 params.clearArea = clearArea;
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001199 params.colorClearValue = clearColorValue;
Shahbaz Youssefi2249d4a2019-04-05 16:48:55 -04001200 params.stencilClearValue = clearStencilValue;
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001201 params.stencilMask = stencilMask;
1202
1203 params.clearColor = true;
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001204 params.clearStencil = clearStencil;
Shahbaz Youssefie3219402018-12-08 16:54:14 +01001205
Shahbaz Youssefi43997012019-03-30 23:24:01 -04001206 const auto &colorRenderTargets = mRenderTargetCache.getColors();
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001207 for (size_t colorIndexGL : clearColorBuffers)
Shahbaz Youssefi43997012019-03-30 23:24:01 -04001208 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001209 const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
Shahbaz Youssefi43997012019-03-30 23:24:01 -04001210 ASSERT(colorRenderTarget);
1211
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001212 params.colorFormat = &colorRenderTarget->getImage().getFormat().imageFormat();
1213 params.colorAttachmentIndexGL = colorIndexGL;
1214 params.colorMaskFlags = colorMaskFlags;
1215 if (mEmulatedAlphaAttachmentMask[colorIndexGL])
Shahbaz Youssefi43997012019-03-30 23:24:01 -04001216 {
1217 params.colorMaskFlags &= ~VK_COLOR_COMPONENT_A_BIT;
1218 }
1219
Geoff Langee244c72019-05-06 10:30:18 -04001220 ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001221
Shahbaz Youssefi2249d4a2019-04-05 16:48:55 -04001222 // Clear stencil only once!
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001223 params.clearStencil = false;
1224 }
1225
Shahbaz Youssefi2249d4a2019-04-05 16:48:55 -04001226 // If there was no color clear, clear stencil alone.
1227 if (params.clearStencil)
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001228 {
1229 params.clearColor = false;
Geoff Langee244c72019-05-06 10:30:18 -04001230 ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
Shahbaz Youssefi43997012019-03-30 23:24:01 -04001231 }
1232
1233 return angle::Result::Continue;
Jamie Madill9aef3672018-04-27 11:45:06 -04001234}
1235
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001236angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
1237 size_t index,
1238 GLfloat *xy) const
JiangYizhoubddc46b2016-12-09 09:50:51 +08001239{
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001240 ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
Jamie Madill7c985f52018-11-29 18:16:17 -05001241 return angle::Result::Stop;
JiangYizhoubddc46b2016-12-09 09:50:51 +08001242}
1243
Jamie Madilld1249de2018-08-28 16:58:53 -04001244angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001245 const gl::Rectangle &renderArea,
Shahbaz Youssefi2660b502019-03-21 12:08:40 -04001246 vk::CommandBuffer **commandBufferOut)
Jamie Madilld1249de2018-08-28 16:58:53 -04001247{
Jamie Madilldf68a6f2017-01-13 17:29:53 -05001248 vk::Framebuffer *framebuffer = nullptr;
Jamie Madill21061022018-07-12 23:56:30 -04001249 ANGLE_TRY(getFramebuffer(contextVk, &framebuffer));
Jamie Madilldf68a6f2017-01-13 17:29:53 -05001250
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001251 vk::AttachmentOpsArray renderPassAttachmentOps;
Jamie Madilldf68a6f2017-01-13 17:29:53 -05001252 std::vector<VkClearValue> attachmentClearValues;
Jamie Madilldf68a6f2017-01-13 17:29:53 -05001253
Shahbaz Youssefi2660b502019-03-21 12:08:40 -04001254 vk::CommandBuffer *writeCommands = nullptr;
Jamie Madille8dd0792018-09-27 15:04:27 -04001255 ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &writeCommands));
Jamie Madille4c5a232018-03-02 21:00:31 -05001256
Jamie Madill49ac74b2017-12-21 14:42:33 -05001257 // Initialize RenderPass info.
Jamie Madill66546be2018-03-08 09:47:20 -05001258 const auto &colorRenderTargets = mRenderTargetCache.getColors();
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001259 for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
Jamie Madill4c26fc22017-02-24 11:04:10 -05001260 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001261 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
Jamie Madill66546be2018-03-08 09:47:20 -05001262 ASSERT(colorRenderTarget);
Jamie Madill49ac74b2017-12-21 14:42:33 -05001263
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001264 ANGLE_TRY(colorRenderTarget->onColorDraw(contextVk, &mFramebuffer, writeCommands));
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001265
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001266 renderPassAttachmentOps.initWithLoadStore(attachmentClearValues.size(),
1267 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1268 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1269 attachmentClearValues.emplace_back(kUninitializedClearValue);
Jamie Madill66546be2018-03-08 09:47:20 -05001270 }
1271
1272 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
1273 if (depthStencilRenderTarget)
1274 {
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001275 ANGLE_TRY(
1276 depthStencilRenderTarget->onDepthStencilDraw(contextVk, &mFramebuffer, writeCommands));
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001277
Shahbaz Youssefidb4ed312019-03-29 00:32:45 -04001278 renderPassAttachmentOps.initWithLoadStore(attachmentClearValues.size(),
1279 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1280 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
1281 attachmentClearValues.emplace_back(kUninitializedClearValue);
Jamie Madill49ac74b2017-12-21 14:42:33 -05001282 }
1283
Jamie Madilldbc605c2019-01-04 16:39:14 -05001284 return mFramebuffer.beginRenderPass(contextVk, *framebuffer, renderArea, mRenderPassDesc,
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001285 renderPassAttachmentOps, attachmentClearValues,
1286 commandBufferOut);
Jamie Madilldf68a6f2017-01-13 17:29:53 -05001287}
1288
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001289void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
Jamie Madill9aef3672018-04-27 11:45:06 -04001290{
Shahbaz Youssefi9fa248e2019-05-06 14:55:18 -04001291 mActiveColorComponentMasksForClear[0].set(colorIndexGL, r);
1292 mActiveColorComponentMasksForClear[1].set(colorIndexGL, g);
1293 mActiveColorComponentMasksForClear[2].set(colorIndexGL, b);
1294 mActiveColorComponentMasksForClear[3].set(colorIndexGL, a);
Luc Ferron5fd36932018-06-19 14:55:50 -04001295}
1296
Shahbaz Youssefie3219402018-12-08 16:54:14 +01001297const gl::DrawBufferMask &FramebufferVk::getEmulatedAlphaAttachmentMask() const
Luc Ferron5fd36932018-06-19 14:55:50 -04001298{
1299 return mEmulatedAlphaAttachmentMask;
Jamie Madill9aef3672018-04-27 11:45:06 -04001300}
Luc Ferron018709f2018-05-10 13:53:11 -04001301
Jamie Madill21061022018-07-12 23:56:30 -04001302angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
1303 const gl::Rectangle &area,
1304 const PackPixelsParams &packPixelsParams,
Jamie Madillb436aac2018-07-18 17:23:48 -04001305 VkImageAspectFlagBits copyAspectFlags,
Jamie Madill21061022018-07-12 23:56:30 -04001306 RenderTargetVk *renderTarget,
1307 void *pixels)
Luc Ferron018709f2018-05-10 13:53:11 -04001308{
Jamie Madill3ea463b2019-06-19 14:21:33 -04001309 ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
Jamie Madill58675012018-05-22 14:54:07 -04001310
Shahbaz Youssefib16d69c2019-05-13 16:28:27 -04001311 RendererVk *renderer = contextVk->getRenderer();
1312
Shahbaz Youssefi2660b502019-03-21 12:08:40 -04001313 vk::CommandBuffer *commandBuffer = nullptr;
Jamie Madille8dd0792018-09-27 15:04:27 -04001314 ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
Jamie Madill58675012018-05-22 14:54:07 -04001315
Jamie Madillbcf467f2018-05-23 09:46:00 -04001316 // Note that although we're reading from the image, we need to update the layout below.
Shahbaz Youssefi7dafe3e2019-01-28 11:39:15 -05001317 vk::ImageHelper *srcImage =
1318 renderTarget->getImageForRead(&mFramebuffer, vk::ImageLayout::TransferSrc, commandBuffer);
Jamie Madillbcf467f2018-05-23 09:46:00 -04001319
Jamie Madill0631e192019-04-18 16:09:12 -04001320 const angle::Format *readFormat = &srcImage->getFormat().imageFormat();
Luc Ferron1617e692018-07-11 11:08:19 -04001321
Jamie Madillb436aac2018-07-18 17:23:48 -04001322 if (copyAspectFlags != VK_IMAGE_ASPECT_COLOR_BIT)
Luc Ferron1617e692018-07-11 11:08:19 -04001323 {
Jamie Madillb436aac2018-07-18 17:23:48 -04001324 readFormat = &GetDepthStencilImageToBufferFormat(*readFormat, copyAspectFlags);
Luc Ferron1617e692018-07-11 11:08:19 -04001325 }
1326
Shahbaz Youssefib16d69c2019-05-13 16:28:27 -04001327 size_t level = renderTarget->getLevelIndex();
1328 size_t layer = renderTarget->getLayerIndex();
1329 VkOffset3D srcOffset = {area.x, area.y, 0};
1330 VkExtent3D srcExtent = {static_cast<uint32_t>(area.width), static_cast<uint32_t>(area.height),
1331 1};
1332
1333 // If the source image is multisampled, we need to resolve it into a temporary image before
1334 // performing a readback.
1335 bool isMultisampled = srcImage->getSamples() > 1;
1336 vk::Scoped<vk::ImageHelper> resolvedImage(contextVk->getDevice());
1337 if (isMultisampled)
1338 {
1339 ANGLE_TRY(resolvedImage.get().init2DStaging(
1340 contextVk, renderer->getMemoryProperties(), gl::Extents(area.width, area.height, 1),
1341 srcImage->getFormat(),
1342 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 1));
Geoff Langee244c72019-05-06 10:30:18 -04001343 resolvedImage.get().updateQueueSerial(contextVk->getCurrentQueueSerial());
Shahbaz Youssefib16d69c2019-05-13 16:28:27 -04001344
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -04001345 // Note: resolve only works on color images (not depth/stencil).
1346 //
1347 // TODO: Currently, depth/stencil blit can perform a depth/stencil readback, but that code
1348 // path will be optimized away. http://anglebug.com/3200
Shahbaz Youssefib16d69c2019-05-13 16:28:27 -04001349 ASSERT(copyAspectFlags == VK_IMAGE_ASPECT_COLOR_BIT);
1350
1351 VkImageResolve resolveRegion = {};
1352 resolveRegion.srcSubresource.aspectMask = copyAspectFlags;
1353 resolveRegion.srcSubresource.mipLevel = level;
1354 resolveRegion.srcSubresource.baseArrayLayer = layer;
1355 resolveRegion.srcSubresource.layerCount = 1;
1356 resolveRegion.srcOffset = srcOffset;
1357 resolveRegion.dstSubresource.aspectMask = copyAspectFlags;
1358 resolveRegion.dstSubresource.mipLevel = 0;
1359 resolveRegion.dstSubresource.baseArrayLayer = 0;
1360 resolveRegion.dstSubresource.layerCount = 1;
1361 resolveRegion.dstOffset = {};
1362 resolveRegion.extent = srcExtent;
1363
1364 srcImage->resolve(&resolvedImage.get(), resolveRegion, commandBuffer);
1365
1366 resolvedImage.get().changeLayout(copyAspectFlags, vk::ImageLayout::TransferSrc,
1367 commandBuffer);
1368
1369 // Make the resolved image the target of buffer copy.
1370 srcImage = &resolvedImage.get();
1371 level = 0;
1372 layer = 0;
1373 srcOffset = {0, 0, 0};
1374 }
1375
Jamie Madillb980c562018-11-27 11:34:27 -05001376 VkBuffer bufferHandle = VK_NULL_HANDLE;
1377 uint8_t *readPixelBuffer = nullptr;
Jamie Madill4c310832018-08-29 13:43:17 -04001378 VkDeviceSize stagingOffset = 0;
Jamie Madillb980c562018-11-27 11:34:27 -05001379 size_t allocationSize = readFormat->pixelBytes * area.width * area.height;
Luc Ferron018709f2018-05-10 13:53:11 -04001380
Jamie Madilld754eb52018-07-19 14:55:03 -04001381 ANGLE_TRY(mReadPixelBuffer.allocate(contextVk, allocationSize, &readPixelBuffer, &bufferHandle,
Shahbaz Youssefi254b32c2018-11-26 11:58:03 -05001382 &stagingOffset, nullptr));
Luc Ferron018709f2018-05-10 13:53:11 -04001383
Shahbaz Youssefi06270c92018-10-03 17:00:25 -04001384 VkBufferImageCopy region = {};
Shahbaz Youssefib16d69c2019-05-13 16:28:27 -04001385 region.bufferImageHeight = srcExtent.height;
Jamie Madill4c310832018-08-29 13:43:17 -04001386 region.bufferOffset = stagingOffset;
Shahbaz Youssefib16d69c2019-05-13 16:28:27 -04001387 region.bufferRowLength = srcExtent.width;
1388 region.imageExtent = srcExtent;
1389 region.imageOffset = srcOffset;
Luc Ferron1617e692018-07-11 11:08:19 -04001390 region.imageSubresource.aspectMask = copyAspectFlags;
Shahbaz Youssefib16d69c2019-05-13 16:28:27 -04001391 region.imageSubresource.baseArrayLayer = layer;
Luc Ferron534b00d2018-05-18 08:16:53 -04001392 region.imageSubresource.layerCount = 1;
Shahbaz Youssefib16d69c2019-05-13 16:28:27 -04001393 region.imageSubresource.mipLevel = level;
Luc Ferron534b00d2018-05-18 08:16:53 -04001394
Jamie Madillbcf467f2018-05-23 09:46:00 -04001395 commandBuffer->copyImageToBuffer(srcImage->getImage(), srcImage->getCurrentLayout(),
1396 bufferHandle, 1, &region);
Luc Ferron018709f2018-05-10 13:53:11 -04001397
1398 // Triggers a full finish.
1399 // TODO(jmadill): Don't block on asynchronous readback.
Geoff Lang892d1802019-03-27 14:21:34 -04001400 ANGLE_TRY(contextVk->finishImpl());
Luc Ferron018709f2018-05-10 13:53:11 -04001401
Luc Ferron534b00d2018-05-18 08:16:53 -04001402 // The buffer we copied to needs to be invalidated before we read from it because its not been
1403 // created with the host coherent bit.
Jamie Madilld754eb52018-07-19 14:55:03 -04001404 ANGLE_TRY(mReadPixelBuffer.invalidate(contextVk));
Yuly Novikov6c6c76c2018-05-17 18:45:06 +00001405
Jamie Madillb436aac2018-07-18 17:23:48 -04001406 PackPixels(packPixelsParams, *readFormat, area.width * readFormat->pixelBytes, readPixelBuffer,
Rafael Cintron05a449a2018-06-20 18:08:04 -07001407 static_cast<uint8_t *>(pixels));
Luc Ferron018709f2018-05-10 13:53:11 -04001408
Jamie Madill7c985f52018-11-29 18:16:17 -05001409 return angle::Result::Continue;
Luc Ferron018709f2018-05-10 13:53:11 -04001410}
Jamie Madill58675012018-05-22 14:54:07 -04001411
Shahbaz Youssefi68549402019-03-25 23:30:49 -04001412gl::Extents FramebufferVk::getReadImageExtents() const
Jamie Madill58675012018-05-22 14:54:07 -04001413{
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001414 ASSERT(getColorReadRenderTarget()->getExtents().width == mState.getDimensions().width);
1415 ASSERT(getColorReadRenderTarget()->getExtents().height == mState.getDimensions().height);
1416
Shahbaz Youssefi68549402019-03-25 23:30:49 -04001417 return getColorReadRenderTarget()->getExtents();
Jamie Madill58675012018-05-22 14:54:07 -04001418}
Jamie Madill502d2e22018-11-01 11:06:23 -04001419
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001420gl::Rectangle FramebufferVk::getCompleteRenderArea() const
1421{
1422 return gl::Rectangle(0, 0, mState.getDimensions().width, mState.getDimensions().height);
1423}
1424
1425gl::Rectangle FramebufferVk::getScissoredRenderArea(ContextVk *contextVk) const
1426{
1427 const gl::Rectangle renderArea(0, 0, mState.getDimensions().width,
1428 mState.getDimensions().height);
1429 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
1430
1431 return ClipRectToScissor(contextVk->getState(), renderArea, invertViewport);
1432}
1433
1434void FramebufferVk::onScissorChange(ContextVk *contextVk)
1435{
1436 gl::Rectangle scissoredRenderArea = getScissoredRenderArea(contextVk);
1437
1438 // If the scissor has grown beyond the previous scissoredRenderArea, make sure the render pass
1439 // is restarted. Otherwise, we can continue using the same renderpass area.
1440 //
1441 // Without a scissor, the render pass area covers the whole of the framebuffer. With a
1442 // scissored clear, the render pass area could be smaller than the framebuffer size. When the
1443 // scissor changes, if the scissor area is completely encompassed by the render pass area, it's
1444 // possible to continue using the same render pass. However, if the current render pass area
1445 // is too small, we need to start a new one. The latter can happen if a scissored clear starts
1446 // a render pass, the scissor is disabled and a draw call is issued to affect the whole
1447 // framebuffer.
Geoff Langee244c72019-05-06 10:30:18 -04001448 mFramebuffer.updateQueueSerial(contextVk->getCurrentQueueSerial());
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001449 if (mFramebuffer.hasStartedRenderPass() &&
1450 !mFramebuffer.getRenderPassRenderArea().encloses(scissoredRenderArea))
1451 {
Geoff Langee244c72019-05-06 10:30:18 -04001452 mFramebuffer.finishCurrentCommands(contextVk);
Shahbaz Youssefi127990f2019-04-04 13:52:04 -04001453 }
1454}
1455
Jamie Madill502d2e22018-11-01 11:06:23 -04001456RenderTargetVk *FramebufferVk::getFirstRenderTarget() const
1457{
1458 for (auto *renderTarget : mRenderTargetCache.getColors())
1459 {
1460 if (renderTarget)
1461 {
1462 return renderTarget;
1463 }
1464 }
1465
1466 return mRenderTargetCache.getDepthStencil();
1467}
1468
1469GLint FramebufferVk::getSamples() const
1470{
1471 RenderTargetVk *firstRT = getFirstRenderTarget();
1472 return firstRT ? firstRT->getImage().getSamples() : 0;
1473}
1474
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001475} // namespace rx