• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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