blob: e9998505c3449a2c80990e0c1e4aa2149a51cd85 [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 Madill7b57b9d2017-01-13 09:33:38 -050016#include "image_util/imageformats.h"
Jamie Madillc564c072017-06-01 12:45:42 -040017#include "libANGLE/Context.h"
18#include "libANGLE/Display.h"
Jamie Madill7b57b9d2017-01-13 09:33:38 -050019#include "libANGLE/formatutils.h"
20#include "libANGLE/renderer/renderer_utils.h"
Jamie Madill1f46bc12018-02-20 16:09:43 -050021#include "libANGLE/renderer/vulkan/CommandGraph.h"
Jamie Madill7b57b9d2017-01-13 09:33:38 -050022#include "libANGLE/renderer/vulkan/ContextVk.h"
Jamie Madill5deea722017-02-16 10:44:46 -050023#include "libANGLE/renderer/vulkan/DisplayVk.h"
Jamie Madill7b57b9d2017-01-13 09:33:38 -050024#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
25#include "libANGLE/renderer/vulkan/RendererVk.h"
26#include "libANGLE/renderer/vulkan/SurfaceVk.h"
Jamie Madill3c424b42018-01-19 12:35:09 -050027#include "libANGLE/renderer/vulkan/vk_format_utils.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040028
29namespace rx
30{
31
Jamie Madill7b57b9d2017-01-13 09:33:38 -050032namespace
33{
Jamie Madill66546be2018-03-08 09:47:20 -050034const gl::InternalFormat &GetReadAttachmentInfo(const gl::Context *context,
35 RenderTargetVk *renderTarget)
Jamie Madill7b57b9d2017-01-13 09:33:38 -050036{
Jamie Madillbc543422018-03-30 10:43:19 -040037 GLenum implFormat =
38 renderTarget->image->getFormat().textureFormat().fboImplementationInternalFormat;
Jamie Madill66546be2018-03-08 09:47:20 -050039 return gl::GetSizedInternalFormatInfo(implFormat);
Jamie Madill7b57b9d2017-01-13 09:33:38 -050040}
Jamie Madill7b57b9d2017-01-13 09:33:38 -050041} // anonymous namespace
42
43// static
44FramebufferVk *FramebufferVk::CreateUserFBO(const gl::FramebufferState &state)
45{
46 return new FramebufferVk(state);
47}
48
49// static
50FramebufferVk *FramebufferVk::CreateDefaultFBO(const gl::FramebufferState &state,
51 WindowSurfaceVk *backbuffer)
52{
53 return new FramebufferVk(state, backbuffer);
54}
55
Jamie Madillab9f9c32017-01-17 17:47:34 -050056FramebufferVk::FramebufferVk(const gl::FramebufferState &state)
Jamie Madill9cceac42018-03-31 14:19:16 -040057 : FramebufferImpl(state), mBackbuffer(nullptr), mRenderPassDesc(), mFramebuffer()
Jamie Madill9e54b5a2016-05-25 12:57:39 -040058{
59}
60
Jamie Madill7b57b9d2017-01-13 09:33:38 -050061FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer)
Jamie Madill9cceac42018-03-31 14:19:16 -040062 : FramebufferImpl(state), mBackbuffer(backbuffer), mRenderPassDesc(), mFramebuffer()
Jamie Madill7b57b9d2017-01-13 09:33:38 -050063{
64}
65
Jamie Madill9e54b5a2016-05-25 12:57:39 -040066FramebufferVk::~FramebufferVk()
67{
68}
69
Jamie Madillc564c072017-06-01 12:45:42 -040070void FramebufferVk::destroy(const gl::Context *context)
Jamie Madill5deea722017-02-16 10:44:46 -050071{
Jamie Madille1f3ad42017-10-28 23:00:42 -040072 RendererVk *renderer = vk::GetImpl(context)->getRenderer();
Jamie Madill5deea722017-02-16 10:44:46 -050073
Jamie Madill526543c2017-10-28 10:59:16 -040074 renderer->releaseResource(*this, &mFramebuffer);
Jamie Madill5deea722017-02-16 10:44:46 -050075}
76
Jamie Madillc564c072017-06-01 12:45:42 -040077void FramebufferVk::destroyDefault(const egl::Display *display)
Jamie Madill5deea722017-02-16 10:44:46 -050078{
Jamie Madille1f3ad42017-10-28 23:00:42 -040079 VkDevice device = vk::GetImpl(display)->getRenderer()->getDevice();
Jamie Madill5deea722017-02-16 10:44:46 -050080
Jamie Madill5deea722017-02-16 10:44:46 -050081 mFramebuffer.destroy(device);
82}
83
Jamie Madill4928b7c2017-06-20 12:57:39 -040084gl::Error FramebufferVk::discard(const gl::Context *context,
85 size_t count,
86 const GLenum *attachments)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040087{
88 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050089 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -040090}
91
Jamie Madill4928b7c2017-06-20 12:57:39 -040092gl::Error FramebufferVk::invalidate(const gl::Context *context,
93 size_t count,
94 const GLenum *attachments)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040095{
96 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050097 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -040098}
99
Jamie Madill4928b7c2017-06-20 12:57:39 -0400100gl::Error FramebufferVk::invalidateSub(const gl::Context *context,
101 size_t count,
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400102 const GLenum *attachments,
103 const gl::Rectangle &area)
104{
105 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500106 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400107}
108
Jamie Madillc564c072017-06-01 12:45:42 -0400109gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400110{
Jamie Madill0cec82a2018-03-14 09:21:07 -0400111 ContextVk *contextVk = vk::GetImpl(context);
112 RendererVk *renderer = contextVk->getRenderer();
113 Serial currentSerial = renderer->getCurrentQueueSerial();
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500114
Jamie Madill0cec82a2018-03-14 09:21:07 -0400115 // This command buffer is only started once.
116 vk::CommandBuffer *commandBuffer = nullptr;
117 vk::CommandGraphNode *writingNode = nullptr;
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500118
Jamie Madill0cec82a2018-03-14 09:21:07 -0400119 const gl::FramebufferAttachment *depthAttachment = mState.getDepthAttachment();
120 bool clearDepth = (depthAttachment && (mask & GL_DEPTH_BUFFER_BIT) != 0);
121 ASSERT(!clearDepth || depthAttachment->isAttached());
122
123 const gl::FramebufferAttachment *stencilAttachment = mState.getStencilAttachment();
124 bool clearStencil = (stencilAttachment && (mask & GL_STENCIL_BUFFER_BIT) != 0);
125 ASSERT(!clearStencil || stencilAttachment->isAttached());
126
Luc Ferrona8af3a62018-03-29 14:44:24 -0400127 bool clearColor = IsMaskFlagSet(static_cast<int>(mask), GL_COLOR_BUFFER_BIT);
128
Luc Ferron8836f632018-04-05 07:26:53 -0400129 const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthStencilAttachment();
Jamie Madilld47044a2018-04-27 11:45:03 -0400130 const gl::State &glState = context->getGLState();
Luc Ferron8836f632018-04-05 07:26:53 -0400131
132 // If we clear the depth OR the stencil but not both, and we have a packed depth stencil
133 // attachment, we need to use clearAttachment instead of clearDepthStencil since Vulkan won't
134 // allow us to clear one or the other separately.
135 bool isSingleClearOnPackedDepthStencilAttachment =
136 depthStencilAttachment && (clearDepth != clearStencil);
Jamie Madilld47044a2018-04-27 11:45:03 -0400137 if (glState.isScissorTestEnabled() || isSingleClearOnPackedDepthStencilAttachment)
Luc Ferrona8af3a62018-03-29 14:44:24 -0400138 {
139 // With scissor test enabled, we clear very differently and we don't need to access
140 // the image inside each attachment we can just use clearCmdAttachments with our
141 // scissor region instead.
Jamie Madillb90779e2018-04-27 11:45:01 -0400142 ANGLE_TRY(clearWithClearAttachments(contextVk, clearColor, clearDepth, clearStencil));
Luc Ferrona8af3a62018-03-29 14:44:24 -0400143 return gl::NoError();
144 }
145
146 // Standard Depth/stencil clear without scissor.
Jamie Madill0cec82a2018-03-14 09:21:07 -0400147 if (clearDepth || clearStencil)
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500148 {
Jamie Madill0cec82a2018-03-14 09:21:07 -0400149 ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
Jamie Madill9cceac42018-03-31 14:19:16 -0400150 writingNode = getCurrentWritingNode();
Jamie Madill0cec82a2018-03-14 09:21:07 -0400151
152 const VkClearDepthStencilValue &clearDepthStencilValue =
153 contextVk->getClearDepthStencilValue().depthStencil;
154
155 // We only support packed depth/stencil, not separate.
Luc Ferron8836f632018-04-05 07:26:53 -0400156 ASSERT(!(clearDepth && clearStencil) || depthStencilAttachment);
Jamie Madill0cec82a2018-03-14 09:21:07 -0400157
Luc Ferrone6a40d02018-03-22 10:30:57 -0400158 const VkImageAspectFlags aspectFlags =
159 (depthAttachment ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
160 (stencilAttachment ? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
Jamie Madill0cec82a2018-03-14 09:21:07 -0400161
162 RenderTargetVk *renderTarget = mRenderTargetCache.getDepthStencil();
163 renderTarget->resource->onWriteResource(writingNode, currentSerial);
Jamie Madill858c1cc2018-03-31 14:19:13 -0400164 renderTarget->image->clearDepthStencil(aspectFlags, clearDepthStencilValue, commandBuffer);
Jamie Madill0cec82a2018-03-14 09:21:07 -0400165
Luc Ferrona8af3a62018-03-29 14:44:24 -0400166 if (!clearColor)
Jamie Madill0cec82a2018-03-14 09:21:07 -0400167 {
168 return gl::NoError();
169 }
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500170 }
171
Luc Ferrona8af3a62018-03-29 14:44:24 -0400172 ASSERT(clearColor);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500173 const auto *attachment = mState.getFirstNonNullAttachment();
174 ASSERT(attachment && attachment->isAttached());
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500175
Jamie Madill0cec82a2018-03-14 09:21:07 -0400176 if (!commandBuffer)
177 {
178 ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
Jamie Madill9cceac42018-03-31 14:19:16 -0400179 writingNode = getCurrentWritingNode();
Jamie Madill0cec82a2018-03-14 09:21:07 -0400180 }
Jamie Madillefb5a5c2018-01-29 15:56:59 -0500181
Jamie Madilld47044a2018-04-27 11:45:03 -0400182 // TODO(jmadill): Check for masked color clear. http://anglebug.com/2455
183
Jamie Madill66546be2018-03-08 09:47:20 -0500184 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
185 const auto &colorRenderTargets = mRenderTargetCache.getColors();
186 for (size_t colorIndex : mState.getEnabledDrawBuffers())
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500187 {
Jamie Madill66546be2018-03-08 09:47:20 -0500188 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
189 ASSERT(colorRenderTarget);
Jamie Madill0cec82a2018-03-14 09:21:07 -0400190 colorRenderTarget->resource->onWriteResource(writingNode, currentSerial);
Jamie Madill858c1cc2018-03-31 14:19:13 -0400191 colorRenderTarget->image->clearColor(contextVk->getClearColorValue().color, commandBuffer);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500192 }
193
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500194 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400195}
196
Jamie Madillc564c072017-06-01 12:45:42 -0400197gl::Error FramebufferVk::clearBufferfv(const gl::Context *context,
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400198 GLenum buffer,
199 GLint drawbuffer,
200 const GLfloat *values)
201{
202 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500203 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400204}
205
Jamie Madillc564c072017-06-01 12:45:42 -0400206gl::Error FramebufferVk::clearBufferuiv(const gl::Context *context,
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400207 GLenum buffer,
208 GLint drawbuffer,
209 const GLuint *values)
210{
211 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500212 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400213}
214
Jamie Madillc564c072017-06-01 12:45:42 -0400215gl::Error FramebufferVk::clearBufferiv(const gl::Context *context,
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400216 GLenum buffer,
217 GLint drawbuffer,
218 const GLint *values)
219{
220 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500221 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400222}
223
Jamie Madillc564c072017-06-01 12:45:42 -0400224gl::Error FramebufferVk::clearBufferfi(const gl::Context *context,
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400225 GLenum buffer,
226 GLint drawbuffer,
227 GLfloat depth,
228 GLint stencil)
229{
230 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500231 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400232}
233
Jamie Madill4928b7c2017-06-20 12:57:39 -0400234GLenum FramebufferVk::getImplementationColorReadFormat(const gl::Context *context) const
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400235{
Jamie Madill66546be2018-03-08 09:47:20 -0500236 return GetReadAttachmentInfo(context, mRenderTargetCache.getColorRead(mState)).format;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400237}
238
Jamie Madill4928b7c2017-06-20 12:57:39 -0400239GLenum FramebufferVk::getImplementationColorReadType(const gl::Context *context) const
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400240{
Jamie Madill66546be2018-03-08 09:47:20 -0500241 return GetReadAttachmentInfo(context, mRenderTargetCache.getColorRead(mState)).type;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400242}
243
Jamie Madillc564c072017-06-01 12:45:42 -0400244gl::Error FramebufferVk::readPixels(const gl::Context *context,
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400245 const gl::Rectangle &area,
246 GLenum format,
247 GLenum type,
Jamie Madilld4826152017-09-21 11:18:59 -0400248 void *pixels)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400249{
Jamie Madill66546be2018-03-08 09:47:20 -0500250 const gl::State &glState = context->getGLState();
Jamie Madille1f3ad42017-10-28 23:00:42 -0400251 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500252 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill5deea722017-02-16 10:44:46 -0500253 VkDevice device = renderer->getDevice();
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500254
Jamie Madill66546be2018-03-08 09:47:20 -0500255 RenderTargetVk *renderTarget = mRenderTargetCache.getColorRead(mState);
256 ASSERT(renderTarget);
257
Jamie Madill93edca12018-03-30 10:43:18 -0400258 vk::ImageHelper stagingImage;
259 ANGLE_TRY(stagingImage.init2DStaging(
Jamie Madillbc543422018-03-30 10:43:19 -0400260 device, renderer->getMemoryProperties(), renderTarget->image->getFormat(),
Jamie Madill93edca12018-03-30 10:43:18 -0400261 gl::Extents(area.width, area.height, 1), vk::StagingUsage::Read));
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500262
Jamie Madill49ac74b2017-12-21 14:42:33 -0500263 vk::CommandBuffer *commandBuffer = nullptr;
Jamie Madill1f46bc12018-02-20 16:09:43 -0500264 ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
Jamie Madilld4826152017-09-21 11:18:59 -0400265
Jamie Madill858c1cc2018-03-31 14:19:13 -0400266 stagingImage.changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL,
267 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
268 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500269
Jamie Madill858c1cc2018-03-31 14:19:13 -0400270 vk::ImageHelper::Copy(renderTarget->image, &stagingImage, gl::Offset(area.x, area.y, 0),
271 gl::Offset(), gl::Extents(area.width, area.height, 1),
272 VK_IMAGE_ASPECT_COLOR_BIT, commandBuffer);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500273
Jamie Madill49ac74b2017-12-21 14:42:33 -0500274 // Triggers a full finish.
275 // TODO(jmadill): Don't block on asynchronous readback.
276 ANGLE_TRY(renderer->finish(context));
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500277
278 // TODO(jmadill): parameters
279 uint8_t *mapPointer = nullptr;
Jamie Madill93edca12018-03-30 10:43:18 -0400280 ANGLE_TRY(stagingImage.getDeviceMemory().map(device, 0, stagingImage.getAllocatedMemorySize(),
281 0, &mapPointer));
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500282
Jamie Madillbc543422018-03-30 10:43:19 -0400283 const angle::Format &angleFormat = renderTarget->image->getFormat().textureFormat();
Jamie Madill6816d842018-03-31 14:19:17 -0400284 GLuint outputPitch = angleFormat.pixelBytes * area.width;
Luc Ferron60284222018-03-20 16:01:44 -0400285
286 // Get the staging image pitch and use it to pack the pixels later.
287 VkSubresourceLayout subresourceLayout;
288 stagingImage.getImage().getSubresourceLayout(device, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
289 &subresourceLayout);
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500290
291 PackPixelsParams params;
292 params.area = area;
293 params.format = format;
294 params.type = type;
Luc Ferron60284222018-03-20 16:01:44 -0400295 params.outputPitch = outputPitch;
Corentin Wallez336129f2017-10-17 15:55:40 -0400296 params.packBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelPack);
Corentin Wallezcda6af12017-10-30 19:20:37 -0400297 params.pack = glState.getPackState();
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500298
Luc Ferron60284222018-03-20 16:01:44 -0400299 PackPixels(params, angleFormat, static_cast<int>(subresourceLayout.rowPitch), mapPointer,
300 reinterpret_cast<uint8_t *>(pixels));
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500301
Jamie Madill5deea722017-02-16 10:44:46 -0500302 stagingImage.getDeviceMemory().unmap(device);
Jamie Madille88ec8e2017-10-31 17:18:14 -0400303 renderer->releaseObject(renderer->getCurrentQueueSerial(), &stagingImage);
Jamie Madillf651c772017-02-21 15:03:51 -0500304
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500305 return vk::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400306}
307
Jamie Madillc564c072017-06-01 12:45:42 -0400308gl::Error FramebufferVk::blit(const gl::Context *context,
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400309 const gl::Rectangle &sourceArea,
310 const gl::Rectangle &destArea,
311 GLbitfield mask,
312 GLenum filter)
313{
314 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500315 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400316}
317
Kenneth Russellce8602a2017-10-03 18:23:08 -0700318bool FramebufferVk::checkStatus(const gl::Context *context) const
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400319{
Jamie Madillb79e7bb2017-10-24 13:55:50 -0400320 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400321}
322
Jamie Madill19fa1c62018-03-08 09:47:21 -0500323gl::Error FramebufferVk::syncState(const gl::Context *context,
324 const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400325{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400326 ContextVk *contextVk = vk::GetImpl(context);
Jamie Madill7bd16662017-10-28 19:40:50 -0400327 RendererVk *renderer = contextVk->getRenderer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400328
329 ASSERT(dirtyBits.any());
Jamie Madill57d9cbb2018-04-27 11:45:04 -0400330 for (size_t dirtyBit : dirtyBits)
331 {
332 switch (dirtyBit)
333 {
334 case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
335 case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
336 ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
337 break;
338 case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
339 case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
340 case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
341 case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
342 case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
343 case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
344 break;
345 default:
346 {
347 ASSERT(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
348 dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
349 size_t colorIndex =
350 static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
351 ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndex));
352 break;
353 }
354 }
355 }
Jamie Madill66546be2018-03-08 09:47:20 -0500356
Jamie Madill9f2a8612017-11-30 12:43:09 -0500357 mRenderPassDesc.reset();
Jamie Madill7bd16662017-10-28 19:40:50 -0400358 renderer->releaseResource(*this, &mFramebuffer);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500359
Jamie Madill9cceac42018-03-31 14:19:16 -0400360 // Trigger a new set of secondary commands next time we render to this FBO.
361 getNewWritingNode(renderer);
Jamie Madill72106562017-03-24 14:18:50 -0400362
Jamie Madill72106562017-03-24 14:18:50 -0400363 contextVk->invalidateCurrentPipeline();
Jamie Madill19fa1c62018-03-08 09:47:21 -0500364
365 return gl::NoError();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500366}
367
Jamie Madillb90779e2018-04-27 11:45:01 -0400368const vk::RenderPassDesc &FramebufferVk::getRenderPassDesc()
Jamie Madillab9f9c32017-01-17 17:47:34 -0500369{
Jamie Madill9f2a8612017-11-30 12:43:09 -0500370 if (mRenderPassDesc.valid())
Jamie Madillab9f9c32017-01-17 17:47:34 -0500371 {
Jamie Madill9f2a8612017-11-30 12:43:09 -0500372 return mRenderPassDesc.value();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500373 }
374
Jamie Madill0b684ce2017-11-23 12:57:39 -0500375 vk::RenderPassDesc desc;
Jamie Madillab9f9c32017-01-17 17:47:34 -0500376
Jamie Madill66546be2018-03-08 09:47:20 -0500377 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
378 const auto &colorRenderTargets = mRenderTargetCache.getColors();
379 for (size_t colorIndex : mState.getEnabledDrawBuffers())
Jamie Madillab9f9c32017-01-17 17:47:34 -0500380 {
Jamie Madill66546be2018-03-08 09:47:20 -0500381 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
382 ASSERT(colorRenderTarget);
Jamie Madillbc543422018-03-30 10:43:19 -0400383 desc.packColorAttachment(*colorRenderTarget->image);
Jamie Madillab9f9c32017-01-17 17:47:34 -0500384 }
385
Jamie Madill66546be2018-03-08 09:47:20 -0500386 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
387 if (depthStencilRenderTarget)
Jamie Madillab9f9c32017-01-17 17:47:34 -0500388 {
Jamie Madillbc543422018-03-30 10:43:19 -0400389 desc.packDepthStencilAttachment(*depthStencilRenderTarget->image);
Jamie Madillab9f9c32017-01-17 17:47:34 -0500390 }
391
Jamie Madill9f2a8612017-11-30 12:43:09 -0500392 mRenderPassDesc = desc;
393 return mRenderPassDesc.value();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500394}
395
Jamie Madillb90779e2018-04-27 11:45:01 -0400396gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(RendererVk *rendererVk)
Jamie Madillab9f9c32017-01-17 17:47:34 -0500397{
398 // If we've already created our cached Framebuffer, return it.
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400399 if (mFramebuffer.valid())
Jamie Madillab9f9c32017-01-17 17:47:34 -0500400 {
401 return &mFramebuffer;
402 }
403
Jamie Madillb90779e2018-04-27 11:45:01 -0400404 const vk::RenderPassDesc &desc = getRenderPassDesc();
Jamie Madill9f2a8612017-11-30 12:43:09 -0500405
Jamie Madillab9f9c32017-01-17 17:47:34 -0500406 vk::RenderPass *renderPass = nullptr;
Jamie Madill9f2a8612017-11-30 12:43:09 -0500407 ANGLE_TRY(rendererVk->getCompatibleRenderPass(desc, &renderPass));
Jamie Madillab9f9c32017-01-17 17:47:34 -0500408
409 // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
Jamie Madill9f2a8612017-11-30 12:43:09 -0500410 VkDevice device = rendererVk->getDevice();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500411 if (mBackbuffer)
412 {
413 return mBackbuffer->getCurrentFramebuffer(device, *renderPass);
414 }
415
416 // Gather VkImageViews over all FBO attachments, also size of attached region.
417 std::vector<VkImageView> attachments;
418 gl::Extents attachmentsSize;
419
Jamie Madill66546be2018-03-08 09:47:20 -0500420 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
421 const auto &colorRenderTargets = mRenderTargetCache.getColors();
422 for (size_t colorIndex : mState.getEnabledDrawBuffers())
Jamie Madillab9f9c32017-01-17 17:47:34 -0500423 {
Jamie Madill66546be2018-03-08 09:47:20 -0500424 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
425 ASSERT(colorRenderTarget);
426 attachments.push_back(colorRenderTarget->imageView->getHandle());
Jamie Madillab9f9c32017-01-17 17:47:34 -0500427
Jamie Madillbc543422018-03-30 10:43:19 -0400428 ASSERT(attachmentsSize.empty() ||
429 attachmentsSize == colorRenderTarget->image->getExtents());
430 attachmentsSize = colorRenderTarget->image->getExtents();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500431 }
432
Jamie Madill66546be2018-03-08 09:47:20 -0500433 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
434 if (depthStencilRenderTarget)
Jamie Madillab9f9c32017-01-17 17:47:34 -0500435 {
Jamie Madill66546be2018-03-08 09:47:20 -0500436 attachments.push_back(depthStencilRenderTarget->imageView->getHandle());
Jamie Madillab9f9c32017-01-17 17:47:34 -0500437
Jamie Madillbc543422018-03-30 10:43:19 -0400438 ASSERT(attachmentsSize.empty() ||
439 attachmentsSize == depthStencilRenderTarget->image->getExtents());
440 attachmentsSize = depthStencilRenderTarget->image->getExtents();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500441 }
442
443 ASSERT(!attachments.empty());
444
445 VkFramebufferCreateInfo framebufferInfo;
446
447 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
448 framebufferInfo.pNext = nullptr;
449 framebufferInfo.flags = 0;
Jamie Madill9f2a8612017-11-30 12:43:09 -0500450 framebufferInfo.renderPass = renderPass->getHandle();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500451 framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
452 framebufferInfo.pAttachments = attachments.data();
453 framebufferInfo.width = static_cast<uint32_t>(attachmentsSize.width);
454 framebufferInfo.height = static_cast<uint32_t>(attachmentsSize.height);
455 framebufferInfo.layers = 1;
456
Jamie Madill25301b62017-10-28 20:59:31 -0400457 ANGLE_TRY(mFramebuffer.init(device, framebufferInfo));
Jamie Madill5deea722017-02-16 10:44:46 -0500458
Jamie Madillab9f9c32017-01-17 17:47:34 -0500459 return &mFramebuffer;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400460}
461
Jamie Madillb90779e2018-04-27 11:45:01 -0400462gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk,
463 bool clearColor,
464 bool clearDepth,
465 bool clearStencil)
Luc Ferron5242d5b2018-02-15 07:14:35 -0500466{
Luc Ferron5242d5b2018-02-15 07:14:35 -0500467 RendererVk *renderer = contextVk->getRenderer();
468
469 // This command can only happen inside a render pass, so obtain one if its already happening
470 // or create a new one if not.
471 vk::CommandGraphNode *node = nullptr;
472 vk::CommandBuffer *commandBuffer = nullptr;
Jamie Madillb90779e2018-04-27 11:45:01 -0400473 ANGLE_TRY(getCommandGraphNodeForDraw(contextVk, &node));
Luc Ferron5242d5b2018-02-15 07:14:35 -0500474 if (node->getInsideRenderPassCommands()->valid())
475 {
476 commandBuffer = node->getInsideRenderPassCommands();
477 }
478 else
479 {
480 ANGLE_TRY(node->beginInsideRenderPassRecording(renderer, &commandBuffer));
481 }
482
Luc Ferrone4c38be2018-04-17 11:09:16 -0400483 // TODO(jmadill): Cube map attachments. http://anglebug.com/2470
484 // We assume for now that we always need to clear only 1 layer starting at the
485 // baseArrayLayer 0, this might need to change depending how we'll implement
486 // cube maps, 3d textures and array textures.
487 VkClearRect clearRect;
488 clearRect.baseArrayLayer = 0;
489 clearRect.layerCount = 1;
490
491 // When clearing, the scissor region must be clipped to the renderArea per the validation rules
492 // in Vulkan.
493 gl::Rectangle intersection;
494 if (!ClipRectangle(contextVk->getGLState().getScissor(), node->getRenderPassRenderArea(),
495 &intersection))
496 {
497 // There is nothing to clear since the scissor is outside of the render area.
498 return gl::NoError();
499 }
500
501 clearRect.rect = gl_vk::GetRect(intersection);
502
Luc Ferron5242d5b2018-02-15 07:14:35 -0500503 gl::AttachmentArray<VkClearAttachment> clearAttachments;
504 int clearAttachmentIndex = 0;
Luc Ferrona8af3a62018-03-29 14:44:24 -0400505
506 if (clearColor)
Luc Ferron5242d5b2018-02-15 07:14:35 -0500507 {
Luc Ferrona8af3a62018-03-29 14:44:24 -0400508 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
509 for (size_t colorIndex : mState.getEnabledDrawBuffers())
510 {
511 VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
512 clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
513 clearAttachment.colorAttachment = static_cast<uint32_t>(colorIndex);
514 clearAttachment.clearValue = contextVk->getClearColorValue();
515 ++clearAttachmentIndex;
516 }
517 }
518
519 if (clearDepth && clearStencil && mState.getDepthStencilAttachment() != nullptr)
520 {
521 // When we have a packed depth/stencil attachment we can do 1 clear for both when it
522 // applies.
Luc Ferron5242d5b2018-02-15 07:14:35 -0500523 VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
Luc Ferrona8af3a62018-03-29 14:44:24 -0400524 clearAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
525 clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
526 clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
Luc Ferron5242d5b2018-02-15 07:14:35 -0500527 ++clearAttachmentIndex;
528 }
Luc Ferrona8af3a62018-03-29 14:44:24 -0400529 else
530 {
531 if (clearDepth)
532 {
533 VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
534 clearAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
535 clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
536 clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
537 ++clearAttachmentIndex;
538 }
539
540 if (clearStencil)
541 {
542 VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
543 clearAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
544 clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
545 clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
546 ++clearAttachmentIndex;
547 }
548 }
Luc Ferron5242d5b2018-02-15 07:14:35 -0500549
Luc Ferrona8af3a62018-03-29 14:44:24 -0400550 commandBuffer->clearAttachments(static_cast<uint32_t>(clearAttachmentIndex),
Luc Ferron5242d5b2018-02-15 07:14:35 -0500551 clearAttachments.data(), 1, &clearRect);
552 return gl::NoError();
553}
554
JiangYizhoubddc46b2016-12-09 09:50:51 +0800555gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const
556{
557 UNIMPLEMENTED();
558 return gl::InternalError() << "getSamplePosition is unimplemented.";
559}
560
Jamie Madillb90779e2018-04-27 11:45:01 -0400561gl::Error FramebufferVk::getCommandGraphNodeForDraw(ContextVk *contextVk,
Jamie Madille4c5a232018-03-02 21:00:31 -0500562 vk::CommandGraphNode **nodeOut)
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500563{
Jamie Madill49ac74b2017-12-21 14:42:33 -0500564 RendererVk *renderer = contextVk->getRenderer();
565 Serial currentSerial = renderer->getCurrentQueueSerial();
Jamie Madillbef918c2017-12-13 13:11:30 -0500566
Jamie Madill9cceac42018-03-31 14:19:16 -0400567 // This will reset the current writing node if it has been completed.
568 updateQueueSerial(currentSerial);
569
570 if (hasChildlessWritingNode())
Jamie Madill4c26fc22017-02-24 11:04:10 -0500571 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400572 *nodeOut = getCurrentWritingNode();
573 }
574 else
575 {
576 *nodeOut = getNewWritingNode(renderer);
Jamie Madill4c26fc22017-02-24 11:04:10 -0500577 }
578
Jamie Madill9cceac42018-03-31 14:19:16 -0400579 if ((*nodeOut)->getInsideRenderPassCommands()->valid())
580 {
581 return gl::NoError();
582 }
Jamie Madill4c26fc22017-02-24 11:04:10 -0500583
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500584 vk::Framebuffer *framebuffer = nullptr;
Jamie Madillb90779e2018-04-27 11:45:01 -0400585 ANGLE_TRY_RESULT(getFramebuffer(renderer), framebuffer);
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500586
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500587 std::vector<VkClearValue> attachmentClearValues;
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500588
Jamie Madille4c5a232018-03-02 21:00:31 -0500589 vk::CommandBuffer *commandBuffer = nullptr;
Jamie Madill9cceac42018-03-31 14:19:16 -0400590 if (!(*nodeOut)->getOutsideRenderPassCommands()->valid())
591 {
592 ANGLE_TRY((*nodeOut)->beginOutsideRenderPassRecording(
593 renderer->getDevice(), renderer->getCommandPool(), &commandBuffer));
594 }
595 else
596 {
597 commandBuffer = (*nodeOut)->getOutsideRenderPassCommands();
598 }
Jamie Madille4c5a232018-03-02 21:00:31 -0500599
Jamie Madill49ac74b2017-12-21 14:42:33 -0500600 // Initialize RenderPass info.
Jamie Madill66546be2018-03-08 09:47:20 -0500601 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
602 const auto &colorRenderTargets = mRenderTargetCache.getColors();
603 for (size_t colorIndex : mState.getEnabledDrawBuffers())
Jamie Madill4c26fc22017-02-24 11:04:10 -0500604 {
Jamie Madill66546be2018-03-08 09:47:20 -0500605 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
606 ASSERT(colorRenderTarget);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500607
Jamie Madill9cceac42018-03-31 14:19:16 -0400608 (*nodeOut)->appendColorRenderTarget(currentSerial, colorRenderTarget);
Jamie Madill66546be2018-03-08 09:47:20 -0500609 attachmentClearValues.emplace_back(contextVk->getClearColorValue());
610 }
611
612 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
613 if (depthStencilRenderTarget)
614 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400615 (*nodeOut)->appendDepthStencilRenderTarget(currentSerial, depthStencilRenderTarget);
Jamie Madillf4d693c2018-02-14 16:38:16 -0500616 attachmentClearValues.emplace_back(contextVk->getClearDepthStencilValue());
Jamie Madill49ac74b2017-12-21 14:42:33 -0500617 }
618
Luc Ferrond17bdfe2018-04-05 13:50:10 -0400619 gl::Rectangle renderArea =
620 gl::Rectangle(0, 0, mState.getDimensions().width, mState.getDimensions().height);
Jamie Madillf4d693c2018-02-14 16:38:16 -0500621 // Hard-code RenderPass to clear the first render target to the current clear value.
622 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
Luc Ferrond17bdfe2018-04-05 13:50:10 -0400623 (*nodeOut)->storeRenderPassInfo(*framebuffer, renderArea, attachmentClearValues);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500624
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500625 return gl::NoError();
626}
627
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400628} // namespace rx