1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // RenderbufferVk.cpp:
7 // Implements the class methods for RenderbufferVk.
8 //
9
10 #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
11
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Image.h"
14 #include "libANGLE/renderer/vulkan/ContextVk.h"
15 #include "libANGLE/renderer/vulkan/ImageVk.h"
16 #include "libANGLE/renderer/vulkan/RendererVk.h"
17
18 namespace rx
19 {
RenderbufferVk(const gl::RenderbufferState & state)20 RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state)
21 : RenderbufferImpl(state), mOwnsImage(false), mImage(nullptr)
22 {}
23
~RenderbufferVk()24 RenderbufferVk::~RenderbufferVk() {}
25
onDestroy(const gl::Context * context)26 void RenderbufferVk::onDestroy(const gl::Context *context)
27 {
28 ContextVk *contextVk = vk::GetImpl(context);
29 releaseAndDeleteImage(contextVk);
30 }
31
setStorageImpl(const gl::Context * context,size_t samples,GLenum internalformat,size_t width,size_t height)32 angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
33 size_t samples,
34 GLenum internalformat,
35 size_t width,
36 size_t height)
37 {
38 ContextVk *contextVk = vk::GetImpl(context);
39 RendererVk *renderer = contextVk->getRenderer();
40 const vk::Format &vkFormat = renderer->getFormat(internalformat);
41
42 if (!mOwnsImage)
43 {
44 releaseAndDeleteImage(contextVk);
45 }
46
47 if (mImage != nullptr && mImage->valid())
48 {
49 // Check against the state if we need to recreate the storage.
50 if (internalformat != mState.getFormat().info->internalFormat ||
51 static_cast<GLsizei>(width) != mState.getWidth() ||
52 static_cast<GLsizei>(height) != mState.getHeight())
53 {
54 releaseImage(contextVk);
55 }
56 }
57
58 if ((mImage == nullptr || !mImage->valid()) && (width != 0 && height != 0))
59 {
60 if (mImage == nullptr)
61 {
62 mImage = new vk::ImageHelper();
63 mOwnsImage = true;
64 }
65
66 const angle::Format &textureFormat = vkFormat.actualImageFormat();
67 bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
68 const VkImageUsageFlags usage =
69 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
70 VK_IMAGE_USAGE_SAMPLED_BIT |
71 (textureFormat.redBits > 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
72 (isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
73
74 VkExtent3D extents = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1u};
75 ANGLE_TRY(mImage->init(contextVk, gl::TextureType::_2D, extents, vkFormat,
76 static_cast<uint32_t>(samples), usage, 0, 0, 1, 1));
77
78 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
79 ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
80
81 mRenderTarget.init(mImage, &mImageViews, 0, 0);
82 }
83
84 return angle::Result::Continue;
85 }
86
setStorage(const gl::Context * context,GLenum internalformat,size_t width,size_t height)87 angle::Result RenderbufferVk::setStorage(const gl::Context *context,
88 GLenum internalformat,
89 size_t width,
90 size_t height)
91 {
92 return setStorageImpl(context, 1, internalformat, width, height);
93 }
94
setStorageMultisample(const gl::Context * context,size_t samples,GLenum internalformat,size_t width,size_t height)95 angle::Result RenderbufferVk::setStorageMultisample(const gl::Context *context,
96 size_t samples,
97 GLenum internalformat,
98 size_t width,
99 size_t height)
100 {
101 return setStorageImpl(context, samples, internalformat, width, height);
102 }
103
setStorageEGLImageTarget(const gl::Context * context,egl::Image * image)104 angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *context,
105 egl::Image *image)
106 {
107 ContextVk *contextVk = vk::GetImpl(context);
108 RendererVk *renderer = contextVk->getRenderer();
109
110 releaseAndDeleteImage(contextVk);
111
112 ImageVk *imageVk = vk::GetImpl(image);
113 mImage = imageVk->getImage();
114 mOwnsImage = false;
115
116 const vk::Format &vkFormat = renderer->getFormat(image->getFormat().info->sizedInternalFormat);
117 const angle::Format &textureFormat = vkFormat.actualImageFormat();
118
119 VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat);
120
121 // Transfer the image to this queue if needed
122 uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
123 if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex))
124 {
125 vk::CommandBuffer *commandBuffer = nullptr;
126 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
127 mImage->changeLayoutAndQueue(aspect, vk::ImageLayout::ColorAttachment,
128 rendererQueueFamilyIndex, commandBuffer);
129 }
130
131 gl::TextureType viewType = imageVk->getImageTextureType();
132
133 if (imageVk->getImageTextureType() == gl::TextureType::CubeMap)
134 {
135 viewType = vk::Get2DTextureType(imageVk->getImage()->getLayerCount(),
136 imageVk->getImage()->getSamples());
137 }
138
139 mRenderTarget.init(mImage, &mImageViews, imageVk->getImageLevel(), imageVk->getImageLayer());
140
141 return angle::Result::Continue;
142 }
143
getAttachmentRenderTarget(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex,GLsizei samples,FramebufferAttachmentRenderTarget ** rtOut)144 angle::Result RenderbufferVk::getAttachmentRenderTarget(const gl::Context *context,
145 GLenum binding,
146 const gl::ImageIndex &imageIndex,
147 GLsizei samples,
148 FramebufferAttachmentRenderTarget **rtOut)
149 {
150 ASSERT(mImage && mImage->valid());
151 ANGLE_TRY(mRenderTarget.flushStagedUpdates(vk::GetImpl(context)));
152 *rtOut = &mRenderTarget;
153 return angle::Result::Continue;
154 }
155
initializeContents(const gl::Context * context,const gl::ImageIndex & imageIndex)156 angle::Result RenderbufferVk::initializeContents(const gl::Context *context,
157 const gl::ImageIndex &imageIndex)
158 {
159 // Note: stageSubresourceRobustClear only uses the intended format to count channels.
160 mImage->stageSubresourceClear(imageIndex);
161 return mImage->flushAllStagedUpdates(vk::GetImpl(context));
162 }
163
releaseOwnershipOfImage(const gl::Context * context)164 void RenderbufferVk::releaseOwnershipOfImage(const gl::Context *context)
165 {
166 ContextVk *contextVk = vk::GetImpl(context);
167
168 mOwnsImage = false;
169 releaseAndDeleteImage(contextVk);
170 }
171
releaseAndDeleteImage(ContextVk * contextVk)172 void RenderbufferVk::releaseAndDeleteImage(ContextVk *contextVk)
173 {
174 releaseImage(contextVk);
175 SafeDelete(mImage);
176 }
177
releaseImage(ContextVk * contextVk)178 void RenderbufferVk::releaseImage(ContextVk *contextVk)
179 {
180 RendererVk *renderer = contextVk->getRenderer();
181
182 if (mImage && mOwnsImage)
183 {
184 mImage->releaseImage(renderer);
185 mImage->releaseStagingBuffer(renderer);
186 }
187 else
188 {
189 mImage = nullptr;
190 }
191
192 mImageViews.release(renderer);
193 }
194
getImplementationSizedFormat() const195 const gl::InternalFormat &RenderbufferVk::getImplementationSizedFormat() const
196 {
197 GLenum internalFormat = mImage->getFormat().actualImageFormat().glInternalFormat;
198 return gl::GetSizedInternalFormatInfo(internalFormat);
199 }
200
getColorReadFormat(const gl::Context * context)201 GLenum RenderbufferVk::getColorReadFormat(const gl::Context *context)
202 {
203 const gl::InternalFormat &sizedFormat = getImplementationSizedFormat();
204 return sizedFormat.format;
205 }
206
getColorReadType(const gl::Context * context)207 GLenum RenderbufferVk::getColorReadType(const gl::Context *context)
208 {
209 const gl::InternalFormat &sizedFormat = getImplementationSizedFormat();
210 return sizedFormat.type;
211 }
212
getRenderbufferImage(const gl::Context * context,const gl::PixelPackState & packState,gl::Buffer * packBuffer,GLenum format,GLenum type,void * pixels)213 angle::Result RenderbufferVk::getRenderbufferImage(const gl::Context *context,
214 const gl::PixelPackState &packState,
215 gl::Buffer *packBuffer,
216 GLenum format,
217 GLenum type,
218 void *pixels)
219 {
220 // Storage not defined.
221 if (!mImage || !mImage->valid())
222 return angle::Result::Continue;
223
224 ContextVk *contextVk = vk::GetImpl(context);
225 ANGLE_TRY(mImage->flushAllStagedUpdates(contextVk));
226 return mImage->readPixelsForGetImage(contextVk, packState, packBuffer, 0, 0, format, type,
227 pixels);
228 }
229 } // namespace rx
230