• 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 {
20 namespace
21 {
22 angle::SubjectIndex kRenderbufferImageSubjectIndex = 0;
23 }  // namespace
24 
RenderbufferVk(const gl::RenderbufferState & state)25 RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state)
26     : RenderbufferImpl(state),
27       mOwnsImage(false),
28       mImage(nullptr),
29       mImageObserverBinding(this, kRenderbufferImageSubjectIndex)
30 {}
31 
~RenderbufferVk()32 RenderbufferVk::~RenderbufferVk() {}
33 
onDestroy(const gl::Context * context)34 void RenderbufferVk::onDestroy(const gl::Context *context)
35 {
36     ContextVk *contextVk = vk::GetImpl(context);
37     releaseAndDeleteImage(contextVk);
38 }
39 
setStorageImpl(const gl::Context * context,size_t samples,GLenum internalformat,size_t width,size_t height)40 angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
41                                              size_t samples,
42                                              GLenum internalformat,
43                                              size_t width,
44                                              size_t height)
45 {
46     ContextVk *contextVk       = vk::GetImpl(context);
47     RendererVk *renderer       = contextVk->getRenderer();
48     const vk::Format &vkFormat = renderer->getFormat(internalformat);
49 
50     if (!mOwnsImage)
51     {
52         releaseAndDeleteImage(contextVk);
53     }
54 
55     if (mImage != nullptr && mImage->valid())
56     {
57         // Check against the state if we need to recreate the storage.
58         if (internalformat != mState.getFormat().info->internalFormat ||
59             static_cast<GLsizei>(width) != mState.getWidth() ||
60             static_cast<GLsizei>(height) != mState.getHeight())
61         {
62             releaseImage(contextVk);
63         }
64     }
65 
66     if ((mImage == nullptr || !mImage->valid()) && (width != 0 && height != 0))
67     {
68         if (mImage == nullptr)
69         {
70             mImage     = new vk::ImageHelper();
71             mOwnsImage = true;
72             mImageObserverBinding.bind(mImage);
73         }
74 
75         const angle::Format &textureFormat = vkFormat.actualImageFormat();
76         bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
77         const VkImageUsageFlags usage =
78             VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
79             VK_IMAGE_USAGE_SAMPLED_BIT |
80             (textureFormat.redBits > 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
81             (isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
82 
83         VkExtent3D extents = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1u};
84         ANGLE_TRY(mImage->init(contextVk, gl::TextureType::_2D, extents, vkFormat,
85                                static_cast<uint32_t>(samples), usage, 0, 0, 1, 1));
86 
87         VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
88         ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
89 
90         mRenderTarget.init(mImage, &mImageViews, 0, 0);
91     }
92 
93     return angle::Result::Continue;
94 }
95 
setStorage(const gl::Context * context,GLenum internalformat,size_t width,size_t height)96 angle::Result RenderbufferVk::setStorage(const gl::Context *context,
97                                          GLenum internalformat,
98                                          size_t width,
99                                          size_t height)
100 {
101     return setStorageImpl(context, 1, internalformat, width, height);
102 }
103 
setStorageMultisample(const gl::Context * context,size_t samples,GLenum internalformat,size_t width,size_t height)104 angle::Result RenderbufferVk::setStorageMultisample(const gl::Context *context,
105                                                     size_t samples,
106                                                     GLenum internalformat,
107                                                     size_t width,
108                                                     size_t height)
109 {
110     return setStorageImpl(context, samples, internalformat, width, height);
111 }
112 
setStorageEGLImageTarget(const gl::Context * context,egl::Image * image)113 angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *context,
114                                                        egl::Image *image)
115 {
116     ContextVk *contextVk = vk::GetImpl(context);
117     RendererVk *renderer = contextVk->getRenderer();
118 
119     releaseAndDeleteImage(contextVk);
120 
121     ImageVk *imageVk = vk::GetImpl(image);
122     mImage           = imageVk->getImage();
123     mOwnsImage       = false;
124     mImageObserverBinding.bind(mImage);
125 
126     const vk::Format &vkFormat = renderer->getFormat(image->getFormat().info->sizedInternalFormat);
127     const angle::Format &textureFormat = vkFormat.actualImageFormat();
128 
129     VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat);
130 
131     // Transfer the image to this queue if needed
132     uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
133     if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex))
134     {
135         vk::CommandBuffer *commandBuffer = nullptr;
136         ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
137         mImage->changeLayoutAndQueue(aspect, vk::ImageLayout::ColorAttachment,
138                                      rendererQueueFamilyIndex, commandBuffer);
139     }
140 
141     gl::TextureType viewType = imageVk->getImageTextureType();
142 
143     if (imageVk->getImageTextureType() == gl::TextureType::CubeMap)
144     {
145         viewType = vk::Get2DTextureType(imageVk->getImage()->getLayerCount(),
146                                         imageVk->getImage()->getSamples());
147     }
148 
149     mRenderTarget.init(mImage, &mImageViews, imageVk->getImageLevel(), imageVk->getImageLayer());
150 
151     return angle::Result::Continue;
152 }
153 
getAttachmentRenderTarget(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex,GLsizei samples,FramebufferAttachmentRenderTarget ** rtOut)154 angle::Result RenderbufferVk::getAttachmentRenderTarget(const gl::Context *context,
155                                                         GLenum binding,
156                                                         const gl::ImageIndex &imageIndex,
157                                                         GLsizei samples,
158                                                         FramebufferAttachmentRenderTarget **rtOut)
159 {
160     ASSERT(mImage && mImage->valid());
161     *rtOut = &mRenderTarget;
162     return angle::Result::Continue;
163 }
164 
initializeContents(const gl::Context * context,const gl::ImageIndex & imageIndex)165 angle::Result RenderbufferVk::initializeContents(const gl::Context *context,
166                                                  const gl::ImageIndex &imageIndex)
167 {
168     // Note: stageSubresourceRobustClear only uses the intended format to count channels.
169     mImage->stageRobustResourceClear(imageIndex);
170     return mImage->flushAllStagedUpdates(vk::GetImpl(context));
171 }
172 
releaseOwnershipOfImage(const gl::Context * context)173 void RenderbufferVk::releaseOwnershipOfImage(const gl::Context *context)
174 {
175     ContextVk *contextVk = vk::GetImpl(context);
176 
177     mOwnsImage = false;
178     releaseAndDeleteImage(contextVk);
179 }
180 
releaseAndDeleteImage(ContextVk * contextVk)181 void RenderbufferVk::releaseAndDeleteImage(ContextVk *contextVk)
182 {
183     releaseImage(contextVk);
184     SafeDelete(mImage);
185     mImageObserverBinding.bind(nullptr);
186 }
187 
releaseImage(ContextVk * contextVk)188 void RenderbufferVk::releaseImage(ContextVk *contextVk)
189 {
190     RendererVk *renderer = contextVk->getRenderer();
191 
192     if (mImage && mOwnsImage)
193     {
194         mImage->releaseImage(renderer);
195         mImage->releaseStagingBuffer(renderer);
196     }
197     else
198     {
199         mImage = nullptr;
200         mImageObserverBinding.bind(nullptr);
201     }
202 
203     mImageViews.release(renderer);
204 }
205 
getImplementationSizedFormat() const206 const gl::InternalFormat &RenderbufferVk::getImplementationSizedFormat() const
207 {
208     GLenum internalFormat = mImage->getFormat().actualImageFormat().glInternalFormat;
209     return gl::GetSizedInternalFormatInfo(internalFormat);
210 }
211 
getColorReadFormat(const gl::Context * context)212 GLenum RenderbufferVk::getColorReadFormat(const gl::Context *context)
213 {
214     const gl::InternalFormat &sizedFormat = getImplementationSizedFormat();
215     return sizedFormat.format;
216 }
217 
getColorReadType(const gl::Context * context)218 GLenum RenderbufferVk::getColorReadType(const gl::Context *context)
219 {
220     const gl::InternalFormat &sizedFormat = getImplementationSizedFormat();
221     return sizedFormat.type;
222 }
223 
getRenderbufferImage(const gl::Context * context,const gl::PixelPackState & packState,gl::Buffer * packBuffer,GLenum format,GLenum type,void * pixels)224 angle::Result RenderbufferVk::getRenderbufferImage(const gl::Context *context,
225                                                    const gl::PixelPackState &packState,
226                                                    gl::Buffer *packBuffer,
227                                                    GLenum format,
228                                                    GLenum type,
229                                                    void *pixels)
230 {
231     // Storage not defined.
232     if (!mImage || !mImage->valid())
233         return angle::Result::Continue;
234 
235     ContextVk *contextVk = vk::GetImpl(context);
236     ANGLE_TRY(mImage->flushAllStagedUpdates(contextVk));
237     return mImage->readPixelsForGetImage(contextVk, packState, packBuffer, 0, 0, format, type,
238                                          pixels);
239 }
240 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)241 void RenderbufferVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
242 {
243     ASSERT(index == kRenderbufferImageSubjectIndex &&
244            message == angle::SubjectMessage::SubjectChanged);
245 
246     // Forward the notification to the parent class that the staging buffer changed.
247     onStateChange(angle::SubjectMessage::SubjectChanged);
248 }
249 }  // namespace rx
250