blob: 522ec4fa77b12efa05905e4ebd41322fc1403ac8 [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 <array>
13#include <vulkan/vulkan.h>
14
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"
17#include "libANGLE/formatutils.h"
18#include "libANGLE/renderer/renderer_utils.h"
19#include "libANGLE/renderer/vulkan/ContextVk.h"
20#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
21#include "libANGLE/renderer/vulkan/RendererVk.h"
22#include "libANGLE/renderer/vulkan/SurfaceVk.h"
23#include "libANGLE/renderer/vulkan/formatutilsvk.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040024
25namespace rx
26{
27
Jamie Madill7b57b9d2017-01-13 09:33:38 -050028namespace
29{
30
31gl::ErrorOrResult<const gl::InternalFormat *> GetReadAttachmentInfo(
32 const gl::FramebufferAttachment *readAttachment)
33{
34 RenderTargetVk *renderTarget = nullptr;
35 ANGLE_TRY(readAttachment->getRenderTarget(&renderTarget));
36
37 GLenum implFormat = renderTarget->format->format().fboImplementationInternalFormat;
38 return &gl::GetInternalFormatInfo(implFormat);
39}
40
Jamie Madillab9f9c32017-01-17 17:47:34 -050041VkSampleCountFlagBits ConvertSamples(GLint sampleCount)
42{
43 switch (sampleCount)
44 {
45 case 0:
46 case 1:
47 return VK_SAMPLE_COUNT_1_BIT;
48 case 2:
49 return VK_SAMPLE_COUNT_2_BIT;
50 case 4:
51 return VK_SAMPLE_COUNT_4_BIT;
52 case 8:
53 return VK_SAMPLE_COUNT_8_BIT;
54 case 16:
55 return VK_SAMPLE_COUNT_16_BIT;
56 case 32:
57 return VK_SAMPLE_COUNT_32_BIT;
58 default:
59 UNREACHABLE();
60 return VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
61 }
62}
63
Jamie Madill7b57b9d2017-01-13 09:33:38 -050064} // anonymous namespace
65
66// static
67FramebufferVk *FramebufferVk::CreateUserFBO(const gl::FramebufferState &state)
68{
69 return new FramebufferVk(state);
70}
71
72// static
73FramebufferVk *FramebufferVk::CreateDefaultFBO(const gl::FramebufferState &state,
74 WindowSurfaceVk *backbuffer)
75{
76 return new FramebufferVk(state, backbuffer);
77}
78
Jamie Madillab9f9c32017-01-17 17:47:34 -050079FramebufferVk::FramebufferVk(const gl::FramebufferState &state)
80 : FramebufferImpl(state),
81 mBackbuffer(nullptr),
82 mRenderPass(VK_NULL_HANDLE),
83 mFramebuffer(VK_NULL_HANDLE)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040084{
85}
86
Jamie Madill7b57b9d2017-01-13 09:33:38 -050087FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer)
Jamie Madillab9f9c32017-01-17 17:47:34 -050088 : FramebufferImpl(state),
89 mBackbuffer(backbuffer),
90 mRenderPass(VK_NULL_HANDLE),
91 mFramebuffer(VK_NULL_HANDLE)
Jamie Madill7b57b9d2017-01-13 09:33:38 -050092{
93}
94
Jamie Madill9e54b5a2016-05-25 12:57:39 -040095FramebufferVk::~FramebufferVk()
96{
97}
98
99gl::Error FramebufferVk::discard(size_t count, const GLenum *attachments)
100{
101 UNIMPLEMENTED();
102 return gl::Error(GL_INVALID_OPERATION);
103}
104
105gl::Error FramebufferVk::invalidate(size_t count, const GLenum *attachments)
106{
107 UNIMPLEMENTED();
108 return gl::Error(GL_INVALID_OPERATION);
109}
110
111gl::Error FramebufferVk::invalidateSub(size_t count,
112 const GLenum *attachments,
113 const gl::Rectangle &area)
114{
115 UNIMPLEMENTED();
116 return gl::Error(GL_INVALID_OPERATION);
117}
118
119gl::Error FramebufferVk::clear(ContextImpl *context, GLbitfield mask)
120{
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500121 ContextVk *contextVk = GetAs<ContextVk>(context);
122
123 if (mState.getDepthAttachment() && (mask & GL_DEPTH_BUFFER_BIT) != 0)
124 {
125 // TODO(jmadill): Depth clear
126 UNIMPLEMENTED();
127 }
128
129 if (mState.getStencilAttachment() && (mask & GL_STENCIL_BUFFER_BIT) != 0)
130 {
131 // TODO(jmadill): Stencil clear
132 UNIMPLEMENTED();
133 }
134
135 if ((mask & GL_COLOR_BUFFER_BIT) == 0)
136 {
137 return gl::NoError();
138 }
139
140 const auto &glState = context->getGLState();
141 const auto &clearColor = glState.getColorClearValue();
142 VkClearColorValue clearColorValue;
143 clearColorValue.float32[0] = clearColor.red;
144 clearColorValue.float32[1] = clearColor.green;
145 clearColorValue.float32[2] = clearColor.blue;
146 clearColorValue.float32[3] = clearColor.alpha;
147
148 // TODO(jmadill): Scissored clears.
149 const auto *attachment = mState.getFirstNonNullAttachment();
150 ASSERT(attachment && attachment->isAttached());
151 const auto &size = attachment->getSize();
152 const gl::Rectangle renderArea(0, 0, size.width, size.height);
153
154 vk::CommandBuffer *commandBuffer = contextVk->getCommandBuffer();
155 ANGLE_TRY(commandBuffer->begin());
156
157 for (const auto &colorAttachment : mState.getColorAttachments())
158 {
159 if (colorAttachment.isAttached())
160 {
161 RenderTargetVk *renderTarget = nullptr;
162 ANGLE_TRY(colorAttachment.getRenderTarget(&renderTarget));
163 renderTarget->image->changeLayoutTop(
164 VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, commandBuffer);
165 commandBuffer->clearSingleColorImage(*renderTarget->image, clearColorValue);
166 }
167 }
168
169 commandBuffer->end();
170
171 ANGLE_TRY(contextVk->submitCommands(*commandBuffer));
172
173 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400174}
175
176gl::Error FramebufferVk::clearBufferfv(ContextImpl *context,
177 GLenum buffer,
178 GLint drawbuffer,
179 const GLfloat *values)
180{
181 UNIMPLEMENTED();
182 return gl::Error(GL_INVALID_OPERATION);
183}
184
185gl::Error FramebufferVk::clearBufferuiv(ContextImpl *context,
186 GLenum buffer,
187 GLint drawbuffer,
188 const GLuint *values)
189{
190 UNIMPLEMENTED();
191 return gl::Error(GL_INVALID_OPERATION);
192}
193
194gl::Error FramebufferVk::clearBufferiv(ContextImpl *context,
195 GLenum buffer,
196 GLint drawbuffer,
197 const GLint *values)
198{
199 UNIMPLEMENTED();
200 return gl::Error(GL_INVALID_OPERATION);
201}
202
203gl::Error FramebufferVk::clearBufferfi(ContextImpl *context,
204 GLenum buffer,
205 GLint drawbuffer,
206 GLfloat depth,
207 GLint stencil)
208{
209 UNIMPLEMENTED();
210 return gl::Error(GL_INVALID_OPERATION);
211}
212
213GLenum FramebufferVk::getImplementationColorReadFormat() const
214{
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500215 auto errOrResult = GetReadAttachmentInfo(mState.getReadAttachment());
216
217 // TODO(jmadill): Handle getRenderTarget error.
218 if (errOrResult.isError())
219 {
220 ERR("Internal error in FramebufferVk::getImplementationColorReadFormat.");
221 return GL_NONE;
222 }
223
224 return errOrResult.getResult()->format;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400225}
226
227GLenum FramebufferVk::getImplementationColorReadType() const
228{
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500229 auto errOrResult = GetReadAttachmentInfo(mState.getReadAttachment());
230
231 // TODO(jmadill): Handle getRenderTarget error.
232 if (errOrResult.isError())
233 {
234 ERR("Internal error in FramebufferVk::getImplementationColorReadFormat.");
235 return GL_NONE;
236 }
237
238 return errOrResult.getResult()->type;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400239}
240
241gl::Error FramebufferVk::readPixels(ContextImpl *context,
242 const gl::Rectangle &area,
243 GLenum format,
244 GLenum type,
245 GLvoid *pixels) const
246{
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500247 const auto &glState = context->getGLState();
248 const auto *readFramebuffer = glState.getReadFramebuffer();
249 const auto *readAttachment = readFramebuffer->getReadColorbuffer();
250
251 RenderTargetVk *renderTarget = nullptr;
252 ANGLE_TRY(readAttachment->getRenderTarget(&renderTarget));
253
254 ContextVk *contextVk = GetAs<ContextVk>(context);
255 RendererVk *renderer = contextVk->getRenderer();
256
257 vk::Image *readImage = renderTarget->image;
258 vk::StagingImage stagingImage;
259 ANGLE_TRY_RESULT(renderer->createStagingImage(TextureDimension::TEX_2D, *renderTarget->format,
260 renderTarget->extents),
261 stagingImage);
262
263 vk::CommandBuffer *commandBuffer = contextVk->getCommandBuffer();
264 commandBuffer->begin();
265 stagingImage.getImage().changeLayoutTop(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL,
266 commandBuffer);
267
268 gl::Box copyRegion;
269 copyRegion.x = area.x;
270 copyRegion.y = area.y;
271 copyRegion.z = 0;
272 copyRegion.width = area.width;
273 copyRegion.height = area.height;
274 copyRegion.depth = 1;
275
276 readImage->changeLayoutTop(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
277 commandBuffer);
278 commandBuffer->copySingleImage(*readImage, stagingImage.getImage(), copyRegion,
279 VK_IMAGE_ASPECT_COLOR_BIT);
280 commandBuffer->end();
281
282 ANGLE_TRY(renderer->submitAndFinishCommandBuffer(*commandBuffer));
283
284 // TODO(jmadill): parameters
285 uint8_t *mapPointer = nullptr;
286 ANGLE_TRY(stagingImage.getDeviceMemory().map(0, stagingImage.getSize(), 0, &mapPointer));
287
288 const auto &angleFormat = renderTarget->format->format();
289
290 // TODO(jmadill): Use pixel bytes from the ANGLE format directly.
291 const auto &glFormat = gl::GetInternalFormatInfo(angleFormat.glInternalFormat);
292 int inputPitch = glFormat.pixelBytes * area.width;
293
294 PackPixelsParams params;
295 params.area = area;
296 params.format = format;
297 params.type = type;
298 params.outputPitch = inputPitch;
299 params.pack = glState.getPackState();
300
301 PackPixels(params, angleFormat, inputPitch, mapPointer, reinterpret_cast<uint8_t *>(pixels));
302
303 stagingImage.getDeviceMemory().unmap();
304
305 return vk::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400306}
307
308gl::Error FramebufferVk::blit(ContextImpl *context,
309 const gl::Rectangle &sourceArea,
310 const gl::Rectangle &destArea,
311 GLbitfield mask,
312 GLenum filter)
313{
314 UNIMPLEMENTED();
315 return gl::Error(GL_INVALID_OPERATION);
316}
317
318bool FramebufferVk::checkStatus() const
319{
320 UNIMPLEMENTED();
321 return bool();
322}
323
324void FramebufferVk::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
325{
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500326 // TODO(jmadill): Smarter update.
Jamie Madillab9f9c32017-01-17 17:47:34 -0500327 mRenderPass = vk::RenderPass();
328 mFramebuffer = vk::Framebuffer();
329}
330
331gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device)
332{
333 if (mRenderPass.valid())
334 {
335 return &mRenderPass;
336 }
337
338 // TODO(jmadill): Can we use stack-only memory?
339 std::vector<VkAttachmentDescription> attachmentDescs;
340 std::vector<VkAttachmentReference> colorAttachmentRefs;
341
342 const auto &colorAttachments = mState.getColorAttachments();
343 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
344 {
345 const auto &colorAttachment = colorAttachments[attachmentIndex];
346 if (colorAttachment.isAttached())
347 {
348 VkAttachmentDescription colorDesc;
349 VkAttachmentReference colorRef;
350
351 RenderTargetVk *renderTarget = nullptr;
352 ANGLE_TRY(colorAttachment.getRenderTarget(&renderTarget));
353
354 // TODO(jmadill): We would only need this flag for duplicated attachments.
355 colorDesc.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
356 colorDesc.format = renderTarget->format->native;
357 colorDesc.samples = ConvertSamples(colorAttachment.getSamples());
358
359 // The load op controls the prior existing depth/color attachment data.
360 // TODO(jmadill): Proper load ops. Should not be hard coded to clear.
361 colorDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
362 colorDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
363 colorDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
364 colorDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
365 colorDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
366 colorDesc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
367
368 colorRef.attachment = static_cast<uint32_t>(colorAttachments.size()) - 1u;
369 colorRef.layout = VK_IMAGE_LAYOUT_GENERAL;
370
371 attachmentDescs.push_back(colorDesc);
372 colorAttachmentRefs.push_back(colorRef);
373 }
374 }
375
376 const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
377 VkAttachmentReference depthStencilAttachmentRef;
378 bool useDepth = depthStencilAttachment && depthStencilAttachment->isAttached();
379
380 if (useDepth)
381 {
382 VkAttachmentDescription depthStencilDesc;
383
384 RenderTargetVk *renderTarget = nullptr;
385 ANGLE_TRY(depthStencilAttachment->getRenderTarget(&renderTarget));
386
387 depthStencilDesc.flags = 0;
388 depthStencilDesc.format = renderTarget->format->native;
389 depthStencilDesc.samples = ConvertSamples(depthStencilAttachment->getSamples());
390 depthStencilDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
391 depthStencilDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
392 depthStencilDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
393 depthStencilDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
394 depthStencilDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
395 depthStencilDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
396
397 depthStencilAttachmentRef.attachment = static_cast<uint32_t>(attachmentDescs.size());
398 depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
399
400 attachmentDescs.push_back(depthStencilDesc);
401 }
402
403 ASSERT(!attachmentDescs.empty());
404
405 VkSubpassDescription subpassDesc;
406
407 subpassDesc.flags = 0;
408 subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
409 subpassDesc.inputAttachmentCount = 0;
410 subpassDesc.pInputAttachments = nullptr;
411 subpassDesc.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
412 subpassDesc.pColorAttachments = colorAttachmentRefs.data();
413 subpassDesc.pResolveAttachments = nullptr;
414 subpassDesc.pDepthStencilAttachment = (useDepth ? &depthStencilAttachmentRef : nullptr);
415 subpassDesc.preserveAttachmentCount = 0;
416 subpassDesc.pPreserveAttachments = nullptr;
417
418 VkRenderPassCreateInfo renderPassInfo;
419
420 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
421 renderPassInfo.pNext = nullptr;
422 renderPassInfo.flags = 0;
423 renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescs.size());
424 renderPassInfo.pAttachments = attachmentDescs.data();
425 renderPassInfo.subpassCount = 1;
426 renderPassInfo.pSubpasses = &subpassDesc;
427 renderPassInfo.dependencyCount = 0;
428 renderPassInfo.pDependencies = nullptr;
429
430 vk::RenderPass renderPass(device);
431 ANGLE_TRY(renderPass.init(renderPassInfo));
432
433 mRenderPass = std::move(renderPass);
434
435 return &mRenderPass;
436}
437
438gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(VkDevice device)
439{
440 // If we've already created our cached Framebuffer, return it.
441 if (mFramebuffer.valid())
442 {
443 return &mFramebuffer;
444 }
445
446 vk::RenderPass *renderPass = nullptr;
447 ANGLE_TRY_RESULT(getRenderPass(device), renderPass);
448
449 // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
450 if (mBackbuffer)
451 {
452 return mBackbuffer->getCurrentFramebuffer(device, *renderPass);
453 }
454
455 // Gather VkImageViews over all FBO attachments, also size of attached region.
456 std::vector<VkImageView> attachments;
457 gl::Extents attachmentsSize;
458
459 const auto &colorAttachments = mState.getColorAttachments();
460 for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
461 {
462 const auto &colorAttachment = colorAttachments[attachmentIndex];
463 if (colorAttachment.isAttached())
464 {
465 RenderTargetVk *renderTarget = nullptr;
466 ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(&renderTarget));
467 attachments.push_back(renderTarget->imageView->getHandle());
468
469 ASSERT(attachmentsSize.empty() || attachmentsSize == colorAttachment.getSize());
470 attachmentsSize = colorAttachment.getSize();
471 }
472 }
473
474 const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
475 if (depthStencilAttachment && depthStencilAttachment->isAttached())
476 {
477 RenderTargetVk *renderTarget = nullptr;
478 ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(&renderTarget));
479 attachments.push_back(renderTarget->imageView->getHandle());
480
481 ASSERT(attachmentsSize.empty() || attachmentsSize == depthStencilAttachment->getSize());
482 attachmentsSize = depthStencilAttachment->getSize();
483 }
484
485 ASSERT(!attachments.empty());
486
487 VkFramebufferCreateInfo framebufferInfo;
488
489 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
490 framebufferInfo.pNext = nullptr;
491 framebufferInfo.flags = 0;
492 framebufferInfo.renderPass = mRenderPass.getHandle();
493 framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
494 framebufferInfo.pAttachments = attachments.data();
495 framebufferInfo.width = static_cast<uint32_t>(attachmentsSize.width);
496 framebufferInfo.height = static_cast<uint32_t>(attachmentsSize.height);
497 framebufferInfo.layers = 1;
498
499 vk::Framebuffer framebuffer(device);
500 ANGLE_TRY(framebuffer.init(framebufferInfo));
501
502 mFramebuffer = std::move(framebuffer);
503
504 return &mFramebuffer;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400505}
506
JiangYizhoubddc46b2016-12-09 09:50:51 +0800507gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const
508{
509 UNIMPLEMENTED();
510 return gl::InternalError() << "getSamplePosition is unimplemented.";
511}
512
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400513} // namespace rx