blob: aed1b6cdc31f2835d1e0877549338ffc5b3fd088 [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 Madill19fa1c62018-03-08 09:47:21 -0500330 ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
Jamie Madill66546be2018-03-08 09:47:20 -0500331
Jamie Madill9f2a8612017-11-30 12:43:09 -0500332 mRenderPassDesc.reset();
Jamie Madill7bd16662017-10-28 19:40:50 -0400333 renderer->releaseResource(*this, &mFramebuffer);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500334
Jamie Madill9cceac42018-03-31 14:19:16 -0400335 // Trigger a new set of secondary commands next time we render to this FBO.
336 getNewWritingNode(renderer);
Jamie Madill72106562017-03-24 14:18:50 -0400337
Jamie Madill72106562017-03-24 14:18:50 -0400338 contextVk->invalidateCurrentPipeline();
Jamie Madill19fa1c62018-03-08 09:47:21 -0500339
340 return gl::NoError();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500341}
342
Jamie Madillb90779e2018-04-27 11:45:01 -0400343const vk::RenderPassDesc &FramebufferVk::getRenderPassDesc()
Jamie Madillab9f9c32017-01-17 17:47:34 -0500344{
Jamie Madill9f2a8612017-11-30 12:43:09 -0500345 if (mRenderPassDesc.valid())
Jamie Madillab9f9c32017-01-17 17:47:34 -0500346 {
Jamie Madill9f2a8612017-11-30 12:43:09 -0500347 return mRenderPassDesc.value();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500348 }
349
Jamie Madill0b684ce2017-11-23 12:57:39 -0500350 vk::RenderPassDesc desc;
Jamie Madillab9f9c32017-01-17 17:47:34 -0500351
Jamie Madill66546be2018-03-08 09:47:20 -0500352 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
353 const auto &colorRenderTargets = mRenderTargetCache.getColors();
354 for (size_t colorIndex : mState.getEnabledDrawBuffers())
Jamie Madillab9f9c32017-01-17 17:47:34 -0500355 {
Jamie Madill66546be2018-03-08 09:47:20 -0500356 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
357 ASSERT(colorRenderTarget);
Jamie Madillbc543422018-03-30 10:43:19 -0400358 desc.packColorAttachment(*colorRenderTarget->image);
Jamie Madillab9f9c32017-01-17 17:47:34 -0500359 }
360
Jamie Madill66546be2018-03-08 09:47:20 -0500361 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
362 if (depthStencilRenderTarget)
Jamie Madillab9f9c32017-01-17 17:47:34 -0500363 {
Jamie Madillbc543422018-03-30 10:43:19 -0400364 desc.packDepthStencilAttachment(*depthStencilRenderTarget->image);
Jamie Madillab9f9c32017-01-17 17:47:34 -0500365 }
366
Jamie Madill9f2a8612017-11-30 12:43:09 -0500367 mRenderPassDesc = desc;
368 return mRenderPassDesc.value();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500369}
370
Jamie Madillb90779e2018-04-27 11:45:01 -0400371gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(RendererVk *rendererVk)
Jamie Madillab9f9c32017-01-17 17:47:34 -0500372{
373 // If we've already created our cached Framebuffer, return it.
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400374 if (mFramebuffer.valid())
Jamie Madillab9f9c32017-01-17 17:47:34 -0500375 {
376 return &mFramebuffer;
377 }
378
Jamie Madillb90779e2018-04-27 11:45:01 -0400379 const vk::RenderPassDesc &desc = getRenderPassDesc();
Jamie Madill9f2a8612017-11-30 12:43:09 -0500380
Jamie Madillab9f9c32017-01-17 17:47:34 -0500381 vk::RenderPass *renderPass = nullptr;
Jamie Madill9f2a8612017-11-30 12:43:09 -0500382 ANGLE_TRY(rendererVk->getCompatibleRenderPass(desc, &renderPass));
Jamie Madillab9f9c32017-01-17 17:47:34 -0500383
384 // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
Jamie Madill9f2a8612017-11-30 12:43:09 -0500385 VkDevice device = rendererVk->getDevice();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500386 if (mBackbuffer)
387 {
388 return mBackbuffer->getCurrentFramebuffer(device, *renderPass);
389 }
390
391 // Gather VkImageViews over all FBO attachments, also size of attached region.
392 std::vector<VkImageView> attachments;
393 gl::Extents attachmentsSize;
394
Jamie Madill66546be2018-03-08 09:47:20 -0500395 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
396 const auto &colorRenderTargets = mRenderTargetCache.getColors();
397 for (size_t colorIndex : mState.getEnabledDrawBuffers())
Jamie Madillab9f9c32017-01-17 17:47:34 -0500398 {
Jamie Madill66546be2018-03-08 09:47:20 -0500399 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
400 ASSERT(colorRenderTarget);
401 attachments.push_back(colorRenderTarget->imageView->getHandle());
Jamie Madillab9f9c32017-01-17 17:47:34 -0500402
Jamie Madillbc543422018-03-30 10:43:19 -0400403 ASSERT(attachmentsSize.empty() ||
404 attachmentsSize == colorRenderTarget->image->getExtents());
405 attachmentsSize = colorRenderTarget->image->getExtents();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500406 }
407
Jamie Madill66546be2018-03-08 09:47:20 -0500408 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
409 if (depthStencilRenderTarget)
Jamie Madillab9f9c32017-01-17 17:47:34 -0500410 {
Jamie Madill66546be2018-03-08 09:47:20 -0500411 attachments.push_back(depthStencilRenderTarget->imageView->getHandle());
Jamie Madillab9f9c32017-01-17 17:47:34 -0500412
Jamie Madillbc543422018-03-30 10:43:19 -0400413 ASSERT(attachmentsSize.empty() ||
414 attachmentsSize == depthStencilRenderTarget->image->getExtents());
415 attachmentsSize = depthStencilRenderTarget->image->getExtents();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500416 }
417
418 ASSERT(!attachments.empty());
419
420 VkFramebufferCreateInfo framebufferInfo;
421
422 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
423 framebufferInfo.pNext = nullptr;
424 framebufferInfo.flags = 0;
Jamie Madill9f2a8612017-11-30 12:43:09 -0500425 framebufferInfo.renderPass = renderPass->getHandle();
Jamie Madillab9f9c32017-01-17 17:47:34 -0500426 framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
427 framebufferInfo.pAttachments = attachments.data();
428 framebufferInfo.width = static_cast<uint32_t>(attachmentsSize.width);
429 framebufferInfo.height = static_cast<uint32_t>(attachmentsSize.height);
430 framebufferInfo.layers = 1;
431
Jamie Madill25301b62017-10-28 20:59:31 -0400432 ANGLE_TRY(mFramebuffer.init(device, framebufferInfo));
Jamie Madill5deea722017-02-16 10:44:46 -0500433
Jamie Madillab9f9c32017-01-17 17:47:34 -0500434 return &mFramebuffer;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400435}
436
Jamie Madillb90779e2018-04-27 11:45:01 -0400437gl::Error FramebufferVk::clearWithClearAttachments(ContextVk *contextVk,
438 bool clearColor,
439 bool clearDepth,
440 bool clearStencil)
Luc Ferron5242d5b2018-02-15 07:14:35 -0500441{
Luc Ferron5242d5b2018-02-15 07:14:35 -0500442 RendererVk *renderer = contextVk->getRenderer();
443
444 // This command can only happen inside a render pass, so obtain one if its already happening
445 // or create a new one if not.
446 vk::CommandGraphNode *node = nullptr;
447 vk::CommandBuffer *commandBuffer = nullptr;
Jamie Madillb90779e2018-04-27 11:45:01 -0400448 ANGLE_TRY(getCommandGraphNodeForDraw(contextVk, &node));
Luc Ferron5242d5b2018-02-15 07:14:35 -0500449 if (node->getInsideRenderPassCommands()->valid())
450 {
451 commandBuffer = node->getInsideRenderPassCommands();
452 }
453 else
454 {
455 ANGLE_TRY(node->beginInsideRenderPassRecording(renderer, &commandBuffer));
456 }
457
Luc Ferrone4c38be2018-04-17 11:09:16 -0400458 // TODO(jmadill): Cube map attachments. http://anglebug.com/2470
459 // We assume for now that we always need to clear only 1 layer starting at the
460 // baseArrayLayer 0, this might need to change depending how we'll implement
461 // cube maps, 3d textures and array textures.
462 VkClearRect clearRect;
463 clearRect.baseArrayLayer = 0;
464 clearRect.layerCount = 1;
465
466 // When clearing, the scissor region must be clipped to the renderArea per the validation rules
467 // in Vulkan.
468 gl::Rectangle intersection;
469 if (!ClipRectangle(contextVk->getGLState().getScissor(), node->getRenderPassRenderArea(),
470 &intersection))
471 {
472 // There is nothing to clear since the scissor is outside of the render area.
473 return gl::NoError();
474 }
475
476 clearRect.rect = gl_vk::GetRect(intersection);
477
Luc Ferron5242d5b2018-02-15 07:14:35 -0500478 gl::AttachmentArray<VkClearAttachment> clearAttachments;
479 int clearAttachmentIndex = 0;
Luc Ferrona8af3a62018-03-29 14:44:24 -0400480
481 if (clearColor)
Luc Ferron5242d5b2018-02-15 07:14:35 -0500482 {
Luc Ferrona8af3a62018-03-29 14:44:24 -0400483 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
484 for (size_t colorIndex : mState.getEnabledDrawBuffers())
485 {
486 VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
487 clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
488 clearAttachment.colorAttachment = static_cast<uint32_t>(colorIndex);
489 clearAttachment.clearValue = contextVk->getClearColorValue();
490 ++clearAttachmentIndex;
491 }
492 }
493
494 if (clearDepth && clearStencil && mState.getDepthStencilAttachment() != nullptr)
495 {
496 // When we have a packed depth/stencil attachment we can do 1 clear for both when it
497 // applies.
Luc Ferron5242d5b2018-02-15 07:14:35 -0500498 VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
Luc Ferrona8af3a62018-03-29 14:44:24 -0400499 clearAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
500 clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
501 clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
Luc Ferron5242d5b2018-02-15 07:14:35 -0500502 ++clearAttachmentIndex;
503 }
Luc Ferrona8af3a62018-03-29 14:44:24 -0400504 else
505 {
506 if (clearDepth)
507 {
508 VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
509 clearAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
510 clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
511 clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
512 ++clearAttachmentIndex;
513 }
514
515 if (clearStencil)
516 {
517 VkClearAttachment &clearAttachment = clearAttachments[clearAttachmentIndex];
518 clearAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
519 clearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
520 clearAttachment.clearValue = contextVk->getClearDepthStencilValue();
521 ++clearAttachmentIndex;
522 }
523 }
Luc Ferron5242d5b2018-02-15 07:14:35 -0500524
Luc Ferrona8af3a62018-03-29 14:44:24 -0400525 commandBuffer->clearAttachments(static_cast<uint32_t>(clearAttachmentIndex),
Luc Ferron5242d5b2018-02-15 07:14:35 -0500526 clearAttachments.data(), 1, &clearRect);
527 return gl::NoError();
528}
529
JiangYizhoubddc46b2016-12-09 09:50:51 +0800530gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const
531{
532 UNIMPLEMENTED();
533 return gl::InternalError() << "getSamplePosition is unimplemented.";
534}
535
Jamie Madillb90779e2018-04-27 11:45:01 -0400536gl::Error FramebufferVk::getCommandGraphNodeForDraw(ContextVk *contextVk,
Jamie Madille4c5a232018-03-02 21:00:31 -0500537 vk::CommandGraphNode **nodeOut)
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500538{
Jamie Madill49ac74b2017-12-21 14:42:33 -0500539 RendererVk *renderer = contextVk->getRenderer();
540 Serial currentSerial = renderer->getCurrentQueueSerial();
Jamie Madillbef918c2017-12-13 13:11:30 -0500541
Jamie Madill9cceac42018-03-31 14:19:16 -0400542 // This will reset the current writing node if it has been completed.
543 updateQueueSerial(currentSerial);
544
545 if (hasChildlessWritingNode())
Jamie Madill4c26fc22017-02-24 11:04:10 -0500546 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400547 *nodeOut = getCurrentWritingNode();
548 }
549 else
550 {
551 *nodeOut = getNewWritingNode(renderer);
Jamie Madill4c26fc22017-02-24 11:04:10 -0500552 }
553
Jamie Madill9cceac42018-03-31 14:19:16 -0400554 if ((*nodeOut)->getInsideRenderPassCommands()->valid())
555 {
556 return gl::NoError();
557 }
Jamie Madill4c26fc22017-02-24 11:04:10 -0500558
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500559 vk::Framebuffer *framebuffer = nullptr;
Jamie Madillb90779e2018-04-27 11:45:01 -0400560 ANGLE_TRY_RESULT(getFramebuffer(renderer), framebuffer);
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500561
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500562 std::vector<VkClearValue> attachmentClearValues;
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500563
Jamie Madille4c5a232018-03-02 21:00:31 -0500564 vk::CommandBuffer *commandBuffer = nullptr;
Jamie Madill9cceac42018-03-31 14:19:16 -0400565 if (!(*nodeOut)->getOutsideRenderPassCommands()->valid())
566 {
567 ANGLE_TRY((*nodeOut)->beginOutsideRenderPassRecording(
568 renderer->getDevice(), renderer->getCommandPool(), &commandBuffer));
569 }
570 else
571 {
572 commandBuffer = (*nodeOut)->getOutsideRenderPassCommands();
573 }
Jamie Madille4c5a232018-03-02 21:00:31 -0500574
Jamie Madill49ac74b2017-12-21 14:42:33 -0500575 // Initialize RenderPass info.
Jamie Madill66546be2018-03-08 09:47:20 -0500576 // TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
577 const auto &colorRenderTargets = mRenderTargetCache.getColors();
578 for (size_t colorIndex : mState.getEnabledDrawBuffers())
Jamie Madill4c26fc22017-02-24 11:04:10 -0500579 {
Jamie Madill66546be2018-03-08 09:47:20 -0500580 RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
581 ASSERT(colorRenderTarget);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500582
Jamie Madill9cceac42018-03-31 14:19:16 -0400583 (*nodeOut)->appendColorRenderTarget(currentSerial, colorRenderTarget);
Jamie Madill66546be2018-03-08 09:47:20 -0500584 attachmentClearValues.emplace_back(contextVk->getClearColorValue());
585 }
586
587 RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
588 if (depthStencilRenderTarget)
589 {
Jamie Madill9cceac42018-03-31 14:19:16 -0400590 (*nodeOut)->appendDepthStencilRenderTarget(currentSerial, depthStencilRenderTarget);
Jamie Madillf4d693c2018-02-14 16:38:16 -0500591 attachmentClearValues.emplace_back(contextVk->getClearDepthStencilValue());
Jamie Madill49ac74b2017-12-21 14:42:33 -0500592 }
593
Luc Ferrond17bdfe2018-04-05 13:50:10 -0400594 gl::Rectangle renderArea =
595 gl::Rectangle(0, 0, mState.getDimensions().width, mState.getDimensions().height);
Jamie Madillf4d693c2018-02-14 16:38:16 -0500596 // Hard-code RenderPass to clear the first render target to the current clear value.
597 // TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
Luc Ferrond17bdfe2018-04-05 13:50:10 -0400598 (*nodeOut)->storeRenderPassInfo(*framebuffer, renderArea, attachmentClearValues);
Jamie Madill49ac74b2017-12-21 14:42:33 -0500599
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500600 return gl::NoError();
601}
602
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400603} // namespace rx