1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // TextureVk.cpp:
7*8975f5c5SAndroid Build Coastguard Worker // Implements the class methods for TextureVk.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/TextureVk.h"
11*8975f5c5SAndroid Build Coastguard Worker #include <vulkan/vulkan.h>
12*8975f5c5SAndroid Build Coastguard Worker
13*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "image_util/generatemip.inc"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Config.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Image.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/MemoryObject.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Surface.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/renderer_utils.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ContextVk.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/FramebufferVk.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ImageVk.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/SurfaceVk.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/UtilsVk.h"
28*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_format_utils.h"
29*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_helpers.h"
30*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_renderer.h"
31*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_utils.h"
32*8975f5c5SAndroid Build Coastguard Worker
33*8975f5c5SAndroid Build Coastguard Worker namespace rx
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker namespace
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageUsageFlags kTransferImageFlags =
38*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
39*8975f5c5SAndroid Build Coastguard Worker
40*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageUsageFlags kColorAttachmentImageFlags =
41*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
42*8975f5c5SAndroid Build Coastguard Worker
43*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageUsageFlags kDrawStagingImageFlags =
44*8975f5c5SAndroid Build Coastguard Worker kTransferImageFlags | kColorAttachmentImageFlags;
45*8975f5c5SAndroid Build Coastguard Worker
46*8975f5c5SAndroid Build Coastguard Worker constexpr VkFormatFeatureFlags kBlitFeatureFlags =
47*8975f5c5SAndroid Build Coastguard Worker VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
48*8975f5c5SAndroid Build Coastguard Worker
49*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageAspectFlags kDepthStencilAspects =
50*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
51*8975f5c5SAndroid Build Coastguard Worker
52*8975f5c5SAndroid Build Coastguard Worker constexpr angle::SubjectIndex kTextureImageSubjectIndex = 0;
53*8975f5c5SAndroid Build Coastguard Worker
54*8975f5c5SAndroid Build Coastguard Worker // Test whether a texture level is within the range of levels for which the current image is
55*8975f5c5SAndroid Build Coastguard Worker // allocated. This is used to ensure out-of-range updates are staged in the image, and not
56*8975f5c5SAndroid Build Coastguard Worker // attempted to be directly applied.
IsTextureLevelInAllocatedImage(const vk::ImageHelper & image,gl::LevelIndex textureLevelIndexGL)57*8975f5c5SAndroid Build Coastguard Worker bool IsTextureLevelInAllocatedImage(const vk::ImageHelper &image,
58*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex textureLevelIndexGL)
59*8975f5c5SAndroid Build Coastguard Worker {
60*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex imageFirstAllocateLevel = image.getFirstAllocatedLevel();
61*8975f5c5SAndroid Build Coastguard Worker if (textureLevelIndexGL < imageFirstAllocateLevel)
62*8975f5c5SAndroid Build Coastguard Worker {
63*8975f5c5SAndroid Build Coastguard Worker return false;
64*8975f5c5SAndroid Build Coastguard Worker }
65*8975f5c5SAndroid Build Coastguard Worker
66*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex imageLevelIndexVk = image.toVkLevel(textureLevelIndexGL);
67*8975f5c5SAndroid Build Coastguard Worker return imageLevelIndexVk < vk::LevelIndex(image.getLevelCount());
68*8975f5c5SAndroid Build Coastguard Worker }
69*8975f5c5SAndroid Build Coastguard Worker
70*8975f5c5SAndroid Build Coastguard Worker // Test whether a redefined texture level is compatible with the currently allocated image. Returns
71*8975f5c5SAndroid Build Coastguard Worker // true if the given size and format match the corresponding mip in the allocated image (taking
72*8975f5c5SAndroid Build Coastguard Worker // base level into account). This could return false when:
73*8975f5c5SAndroid Build Coastguard Worker //
74*8975f5c5SAndroid Build Coastguard Worker // - Defining a texture level that is outside the range of the image levels. In this case, changes
75*8975f5c5SAndroid Build Coastguard Worker // to this level should remain staged until the texture is redefined to include this level.
76*8975f5c5SAndroid Build Coastguard Worker // - Redefining a texture level that is within the range of the image levels, but has a different
77*8975f5c5SAndroid Build Coastguard Worker // size or format. In this case too, changes to this level should remain staged as the texture
78*8975f5c5SAndroid Build Coastguard Worker // is no longer complete as is.
IsTextureLevelDefinitionCompatibleWithImage(const vk::ImageHelper & image,gl::LevelIndex textureLevelIndexGL,const gl::Extents & size,angle::FormatID intendedFormatID,angle::FormatID actualFormatID)79*8975f5c5SAndroid Build Coastguard Worker bool IsTextureLevelDefinitionCompatibleWithImage(const vk::ImageHelper &image,
80*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex textureLevelIndexGL,
81*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size,
82*8975f5c5SAndroid Build Coastguard Worker angle::FormatID intendedFormatID,
83*8975f5c5SAndroid Build Coastguard Worker angle::FormatID actualFormatID)
84*8975f5c5SAndroid Build Coastguard Worker {
85*8975f5c5SAndroid Build Coastguard Worker if (!IsTextureLevelInAllocatedImage(image, textureLevelIndexGL))
86*8975f5c5SAndroid Build Coastguard Worker {
87*8975f5c5SAndroid Build Coastguard Worker return false;
88*8975f5c5SAndroid Build Coastguard Worker }
89*8975f5c5SAndroid Build Coastguard Worker
90*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex imageLevelIndexVk = image.toVkLevel(textureLevelIndexGL);
91*8975f5c5SAndroid Build Coastguard Worker return size == image.getLevelExtents(imageLevelIndexVk) &&
92*8975f5c5SAndroid Build Coastguard Worker intendedFormatID == image.getIntendedFormatID() &&
93*8975f5c5SAndroid Build Coastguard Worker actualFormatID == image.getActualFormatID();
94*8975f5c5SAndroid Build Coastguard Worker }
95*8975f5c5SAndroid Build Coastguard Worker
CanCopyWithTransferForTexImage(vk::Renderer * renderer,angle::FormatID srcIntendedFormatID,angle::FormatID srcActualFormatID,VkImageTiling srcTilingMode,angle::FormatID dstIntendedFormatID,angle::FormatID dstActualFormatID,VkImageTiling dstTilingMode,bool isViewportFlipY)96*8975f5c5SAndroid Build Coastguard Worker bool CanCopyWithTransferForTexImage(vk::Renderer *renderer,
97*8975f5c5SAndroid Build Coastguard Worker angle::FormatID srcIntendedFormatID,
98*8975f5c5SAndroid Build Coastguard Worker angle::FormatID srcActualFormatID,
99*8975f5c5SAndroid Build Coastguard Worker VkImageTiling srcTilingMode,
100*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstIntendedFormatID,
101*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstActualFormatID,
102*8975f5c5SAndroid Build Coastguard Worker VkImageTiling dstTilingMode,
103*8975f5c5SAndroid Build Coastguard Worker bool isViewportFlipY)
104*8975f5c5SAndroid Build Coastguard Worker {
105*8975f5c5SAndroid Build Coastguard Worker // For glTex[Sub]Image, only accept same-format transfers.
106*8975f5c5SAndroid Build Coastguard Worker // There are cases that two images' actual format is the same, but intended formats are
107*8975f5c5SAndroid Build Coastguard Worker // different due to one is using the fallback format (for example, RGB fallback to RGBA). In
108*8975f5c5SAndroid Build Coastguard Worker // these situations CanCopyWithTransfer will say yes. But if we use transfer to do copy, the
109*8975f5c5SAndroid Build Coastguard Worker // alpha channel will be also be copied with source data which is wrong.
110*8975f5c5SAndroid Build Coastguard Worker bool isFormatCompatible =
111*8975f5c5SAndroid Build Coastguard Worker srcIntendedFormatID == dstIntendedFormatID && srcActualFormatID == dstActualFormatID;
112*8975f5c5SAndroid Build Coastguard Worker
113*8975f5c5SAndroid Build Coastguard Worker return !isViewportFlipY && isFormatCompatible &&
114*8975f5c5SAndroid Build Coastguard Worker vk::CanCopyWithTransfer(renderer, srcActualFormatID, srcTilingMode, dstActualFormatID,
115*8975f5c5SAndroid Build Coastguard Worker dstTilingMode);
116*8975f5c5SAndroid Build Coastguard Worker }
117*8975f5c5SAndroid Build Coastguard Worker
CanCopyWithTransferForCopyTexture(vk::Renderer * renderer,const vk::ImageHelper & srcImage,VkImageTiling srcTilingMode,angle::FormatID destIntendedFormatID,angle::FormatID destActualFormatID,VkImageTiling destTilingMode,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)118*8975f5c5SAndroid Build Coastguard Worker bool CanCopyWithTransferForCopyTexture(vk::Renderer *renderer,
119*8975f5c5SAndroid Build Coastguard Worker const vk::ImageHelper &srcImage,
120*8975f5c5SAndroid Build Coastguard Worker VkImageTiling srcTilingMode,
121*8975f5c5SAndroid Build Coastguard Worker angle::FormatID destIntendedFormatID,
122*8975f5c5SAndroid Build Coastguard Worker angle::FormatID destActualFormatID,
123*8975f5c5SAndroid Build Coastguard Worker VkImageTiling destTilingMode,
124*8975f5c5SAndroid Build Coastguard Worker bool unpackFlipY,
125*8975f5c5SAndroid Build Coastguard Worker bool unpackPremultiplyAlpha,
126*8975f5c5SAndroid Build Coastguard Worker bool unpackUnmultiplyAlpha)
127*8975f5c5SAndroid Build Coastguard Worker {
128*8975f5c5SAndroid Build Coastguard Worker if (unpackFlipY || unpackPremultiplyAlpha || unpackUnmultiplyAlpha)
129*8975f5c5SAndroid Build Coastguard Worker {
130*8975f5c5SAndroid Build Coastguard Worker return false;
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker
133*8975f5c5SAndroid Build Coastguard Worker if (!vk::CanCopyWithTransfer(renderer, srcImage.getActualFormatID(), srcTilingMode,
134*8975f5c5SAndroid Build Coastguard Worker destActualFormatID, destTilingMode))
135*8975f5c5SAndroid Build Coastguard Worker {
136*8975f5c5SAndroid Build Coastguard Worker return false;
137*8975f5c5SAndroid Build Coastguard Worker }
138*8975f5c5SAndroid Build Coastguard Worker
139*8975f5c5SAndroid Build Coastguard Worker // If the formats are identical, we can always transfer between them.
140*8975f5c5SAndroid Build Coastguard Worker if (srcImage.getIntendedFormatID() == destIntendedFormatID &&
141*8975f5c5SAndroid Build Coastguard Worker srcImage.getActualFormatID() == destActualFormatID)
142*8975f5c5SAndroid Build Coastguard Worker {
143*8975f5c5SAndroid Build Coastguard Worker return true;
144*8975f5c5SAndroid Build Coastguard Worker }
145*8975f5c5SAndroid Build Coastguard Worker
146*8975f5c5SAndroid Build Coastguard Worker // If either format is emulated, cannot transfer.
147*8975f5c5SAndroid Build Coastguard Worker if (srcImage.hasEmulatedImageFormat() ||
148*8975f5c5SAndroid Build Coastguard Worker vk::HasEmulatedImageFormat(destIntendedFormatID, destActualFormatID))
149*8975f5c5SAndroid Build Coastguard Worker {
150*8975f5c5SAndroid Build Coastguard Worker return false;
151*8975f5c5SAndroid Build Coastguard Worker }
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker // Otherwise, allow transfer between compatible formats. This is derived from the specification
154*8975f5c5SAndroid Build Coastguard Worker // of CHROMIUM_copy_texture.
155*8975f5c5SAndroid Build Coastguard Worker const angle::Format &srcAngleFormat = srcImage.getActualFormat();
156*8975f5c5SAndroid Build Coastguard Worker const angle::Format &destAngleFormat = angle::Format::Get(destActualFormatID);
157*8975f5c5SAndroid Build Coastguard Worker
158*8975f5c5SAndroid Build Coastguard Worker const bool srcIsBGRA = srcAngleFormat.isBGRA();
159*8975f5c5SAndroid Build Coastguard Worker const bool srcHasR8 = srcAngleFormat.redBits == 8;
160*8975f5c5SAndroid Build Coastguard Worker const bool srcHasG8 = srcAngleFormat.greenBits == 8;
161*8975f5c5SAndroid Build Coastguard Worker const bool srcHasB8 = srcAngleFormat.blueBits == 8;
162*8975f5c5SAndroid Build Coastguard Worker const bool srcHasA8 = srcAngleFormat.alphaBits == 8;
163*8975f5c5SAndroid Build Coastguard Worker const bool srcIsSigned = srcAngleFormat.isSnorm() || srcAngleFormat.isSint();
164*8975f5c5SAndroid Build Coastguard Worker
165*8975f5c5SAndroid Build Coastguard Worker const bool destIsBGRA = destAngleFormat.isBGRA();
166*8975f5c5SAndroid Build Coastguard Worker const bool destHasR8 = destAngleFormat.redBits == 8;
167*8975f5c5SAndroid Build Coastguard Worker const bool destHasG8 = destAngleFormat.greenBits == 8;
168*8975f5c5SAndroid Build Coastguard Worker const bool destHasB8 = destAngleFormat.blueBits == 8;
169*8975f5c5SAndroid Build Coastguard Worker const bool destHasA8 = destAngleFormat.alphaBits == 8;
170*8975f5c5SAndroid Build Coastguard Worker const bool destIsSigned = destAngleFormat.isSnorm() || destAngleFormat.isSint();
171*8975f5c5SAndroid Build Coastguard Worker
172*8975f5c5SAndroid Build Coastguard Worker // Copy is allowed as long as they have the same number, ordering and sign of (8-bit) channels.
173*8975f5c5SAndroid Build Coastguard Worker // CHROMIUM_copy_texture expects verbatim copy between these format, so this copy is done
174*8975f5c5SAndroid Build Coastguard Worker // regardless of sRGB, normalized, etc.
175*8975f5c5SAndroid Build Coastguard Worker return srcIsBGRA == destIsBGRA && srcHasR8 == destHasR8 && srcHasG8 == destHasG8 &&
176*8975f5c5SAndroid Build Coastguard Worker srcHasB8 == destHasB8 && srcHasA8 == destHasA8 && srcIsSigned == destIsSigned;
177*8975f5c5SAndroid Build Coastguard Worker }
178*8975f5c5SAndroid Build Coastguard Worker
CanCopyWithDraw(vk::Renderer * renderer,const angle::FormatID srcFormatID,VkImageTiling srcTilingMode,const angle::FormatID dstFormatID,VkImageTiling destTilingMode)179*8975f5c5SAndroid Build Coastguard Worker bool CanCopyWithDraw(vk::Renderer *renderer,
180*8975f5c5SAndroid Build Coastguard Worker const angle::FormatID srcFormatID,
181*8975f5c5SAndroid Build Coastguard Worker VkImageTiling srcTilingMode,
182*8975f5c5SAndroid Build Coastguard Worker const angle::FormatID dstFormatID,
183*8975f5c5SAndroid Build Coastguard Worker VkImageTiling destTilingMode)
184*8975f5c5SAndroid Build Coastguard Worker {
185*8975f5c5SAndroid Build Coastguard Worker // Checks that the formats in copy by drawing have the appropriate feature bits
186*8975f5c5SAndroid Build Coastguard Worker bool srcFormatHasNecessaryFeature = vk::FormatHasNecessaryFeature(
187*8975f5c5SAndroid Build Coastguard Worker renderer, srcFormatID, srcTilingMode, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
188*8975f5c5SAndroid Build Coastguard Worker bool dstFormatHasNecessaryFeature = vk::FormatHasNecessaryFeature(
189*8975f5c5SAndroid Build Coastguard Worker renderer, dstFormatID, destTilingMode, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
190*8975f5c5SAndroid Build Coastguard Worker
191*8975f5c5SAndroid Build Coastguard Worker return srcFormatHasNecessaryFeature && dstFormatHasNecessaryFeature;
192*8975f5c5SAndroid Build Coastguard Worker }
193*8975f5c5SAndroid Build Coastguard Worker
CanGenerateMipmapWithCompute(vk::Renderer * renderer,VkImageType imageType,angle::FormatID formatID,GLint samples,bool canBeRespecified)194*8975f5c5SAndroid Build Coastguard Worker bool CanGenerateMipmapWithCompute(vk::Renderer *renderer,
195*8975f5c5SAndroid Build Coastguard Worker VkImageType imageType,
196*8975f5c5SAndroid Build Coastguard Worker angle::FormatID formatID,
197*8975f5c5SAndroid Build Coastguard Worker GLint samples,
198*8975f5c5SAndroid Build Coastguard Worker bool canBeRespecified)
199*8975f5c5SAndroid Build Coastguard Worker {
200*8975f5c5SAndroid Build Coastguard Worker // Feature needs to be enabled
201*8975f5c5SAndroid Build Coastguard Worker if (!renderer->getFeatures().allowGenerateMipmapWithCompute.enabled)
202*8975f5c5SAndroid Build Coastguard Worker {
203*8975f5c5SAndroid Build Coastguard Worker return false;
204*8975f5c5SAndroid Build Coastguard Worker }
205*8975f5c5SAndroid Build Coastguard Worker
206*8975f5c5SAndroid Build Coastguard Worker // We need to be able to respecify the backing image
207*8975f5c5SAndroid Build Coastguard Worker if (!canBeRespecified)
208*8975f5c5SAndroid Build Coastguard Worker {
209*8975f5c5SAndroid Build Coastguard Worker return false;
210*8975f5c5SAndroid Build Coastguard Worker }
211*8975f5c5SAndroid Build Coastguard Worker
212*8975f5c5SAndroid Build Coastguard Worker const angle::Format &angleFormat = angle::Format::Get(formatID);
213*8975f5c5SAndroid Build Coastguard Worker // Format must have STORAGE support.
214*8975f5c5SAndroid Build Coastguard Worker const bool hasStorageSupport =
215*8975f5c5SAndroid Build Coastguard Worker renderer->hasImageFormatFeatureBits(formatID, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT);
216*8975f5c5SAndroid Build Coastguard Worker
217*8975f5c5SAndroid Build Coastguard Worker // No support for sRGB formats yet.
218*8975f5c5SAndroid Build Coastguard Worker const bool isSRGB = angleFormat.isSRGB;
219*8975f5c5SAndroid Build Coastguard Worker
220*8975f5c5SAndroid Build Coastguard Worker // No support for integer formats yet.
221*8975f5c5SAndroid Build Coastguard Worker const bool isInt = angleFormat.isInt();
222*8975f5c5SAndroid Build Coastguard Worker
223*8975f5c5SAndroid Build Coastguard Worker // Only 2D images are supported.
224*8975f5c5SAndroid Build Coastguard Worker const bool is2D = imageType == VK_IMAGE_TYPE_2D;
225*8975f5c5SAndroid Build Coastguard Worker
226*8975f5c5SAndroid Build Coastguard Worker // No support for multisampled images yet.
227*8975f5c5SAndroid Build Coastguard Worker const bool isMultisampled = samples > 1;
228*8975f5c5SAndroid Build Coastguard Worker
229*8975f5c5SAndroid Build Coastguard Worker // Only color formats are supported.
230*8975f5c5SAndroid Build Coastguard Worker const bool isColorFormat = !angleFormat.hasDepthOrStencilBits();
231*8975f5c5SAndroid Build Coastguard Worker
232*8975f5c5SAndroid Build Coastguard Worker return hasStorageSupport && !isSRGB && !isInt && is2D && !isMultisampled && isColorFormat;
233*8975f5c5SAndroid Build Coastguard Worker }
234*8975f5c5SAndroid Build Coastguard Worker
GetRenderTargetLayerCountAndIndex(vk::ImageHelper * image,const gl::ImageIndex & index,GLuint * layerIndex,GLuint * layerCount,GLuint * imageLayerCount)235*8975f5c5SAndroid Build Coastguard Worker void GetRenderTargetLayerCountAndIndex(vk::ImageHelper *image,
236*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
237*8975f5c5SAndroid Build Coastguard Worker GLuint *layerIndex,
238*8975f5c5SAndroid Build Coastguard Worker GLuint *layerCount,
239*8975f5c5SAndroid Build Coastguard Worker GLuint *imageLayerCount)
240*8975f5c5SAndroid Build Coastguard Worker {
241*8975f5c5SAndroid Build Coastguard Worker *layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
242*8975f5c5SAndroid Build Coastguard Worker *layerCount = index.getLayerCount();
243*8975f5c5SAndroid Build Coastguard Worker
244*8975f5c5SAndroid Build Coastguard Worker switch (index.getType())
245*8975f5c5SAndroid Build Coastguard Worker {
246*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_2D:
247*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_2DMultisample:
248*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::External:
249*8975f5c5SAndroid Build Coastguard Worker ASSERT(*layerIndex == 0 &&
250*8975f5c5SAndroid Build Coastguard Worker (*layerCount == 1 ||
251*8975f5c5SAndroid Build Coastguard Worker *layerCount == static_cast<GLuint>(gl::ImageIndex::kEntireLevel)));
252*8975f5c5SAndroid Build Coastguard Worker *imageLayerCount = 1;
253*8975f5c5SAndroid Build Coastguard Worker break;
254*8975f5c5SAndroid Build Coastguard Worker
255*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::CubeMap:
256*8975f5c5SAndroid Build Coastguard Worker ASSERT(!index.hasLayer() ||
257*8975f5c5SAndroid Build Coastguard Worker *layerIndex == static_cast<GLuint>(index.cubeMapFaceIndex()));
258*8975f5c5SAndroid Build Coastguard Worker *imageLayerCount = gl::kCubeFaceCount;
259*8975f5c5SAndroid Build Coastguard Worker break;
260*8975f5c5SAndroid Build Coastguard Worker
261*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_3D:
262*8975f5c5SAndroid Build Coastguard Worker {
263*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex levelGL(index.getLevelIndex());
264*8975f5c5SAndroid Build Coastguard Worker *imageLayerCount = image->getLevelExtents(image->toVkLevel(levelGL)).depth;
265*8975f5c5SAndroid Build Coastguard Worker break;
266*8975f5c5SAndroid Build Coastguard Worker }
267*8975f5c5SAndroid Build Coastguard Worker
268*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_2DArray:
269*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_2DMultisampleArray:
270*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::CubeMapArray:
271*8975f5c5SAndroid Build Coastguard Worker *imageLayerCount = image->getLayerCount();
272*8975f5c5SAndroid Build Coastguard Worker break;
273*8975f5c5SAndroid Build Coastguard Worker
274*8975f5c5SAndroid Build Coastguard Worker default:
275*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
276*8975f5c5SAndroid Build Coastguard Worker }
277*8975f5c5SAndroid Build Coastguard Worker
278*8975f5c5SAndroid Build Coastguard Worker if (*layerCount == static_cast<GLuint>(gl::ImageIndex::kEntireLevel))
279*8975f5c5SAndroid Build Coastguard Worker {
280*8975f5c5SAndroid Build Coastguard Worker ASSERT(*layerIndex == 0);
281*8975f5c5SAndroid Build Coastguard Worker *layerCount = *imageLayerCount;
282*8975f5c5SAndroid Build Coastguard Worker }
283*8975f5c5SAndroid Build Coastguard Worker }
284*8975f5c5SAndroid Build Coastguard Worker
Set3DBaseArrayLayerAndLayerCount(VkImageSubresourceLayers * Subresource)285*8975f5c5SAndroid Build Coastguard Worker void Set3DBaseArrayLayerAndLayerCount(VkImageSubresourceLayers *Subresource)
286*8975f5c5SAndroid Build Coastguard Worker {
287*8975f5c5SAndroid Build Coastguard Worker // If the srcImage/dstImage parameters are of VkImageType VK_IMAGE_TYPE_3D, the baseArrayLayer
288*8975f5c5SAndroid Build Coastguard Worker // and layerCount members of the corresponding subresource must be 0 and 1, respectively.
289*8975f5c5SAndroid Build Coastguard Worker Subresource->baseArrayLayer = 0;
290*8975f5c5SAndroid Build Coastguard Worker Subresource->layerCount = 1;
291*8975f5c5SAndroid Build Coastguard Worker }
292*8975f5c5SAndroid Build Coastguard Worker
AdjustStorageViewFormatPerWorkarounds(vk::Renderer * renderer,const vk::Format * intended,vk::ImageAccess access)293*8975f5c5SAndroid Build Coastguard Worker const vk::Format *AdjustStorageViewFormatPerWorkarounds(vk::Renderer *renderer,
294*8975f5c5SAndroid Build Coastguard Worker const vk::Format *intended,
295*8975f5c5SAndroid Build Coastguard Worker vk::ImageAccess access)
296*8975f5c5SAndroid Build Coastguard Worker {
297*8975f5c5SAndroid Build Coastguard Worker // r32f images are emulated with r32ui.
298*8975f5c5SAndroid Build Coastguard Worker if (renderer->getFeatures().emulateR32fImageAtomicExchange.enabled &&
299*8975f5c5SAndroid Build Coastguard Worker intended->getActualImageFormatID(access) == angle::FormatID::R32_FLOAT)
300*8975f5c5SAndroid Build Coastguard Worker {
301*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32_UINT);
302*8975f5c5SAndroid Build Coastguard Worker }
303*8975f5c5SAndroid Build Coastguard Worker
304*8975f5c5SAndroid Build Coastguard Worker return intended;
305*8975f5c5SAndroid Build Coastguard Worker }
306*8975f5c5SAndroid Build Coastguard Worker
AdjustViewFormatForSampler(vk::Renderer * renderer,const vk::Format * intended,gl::SamplerFormat samplerFormat)307*8975f5c5SAndroid Build Coastguard Worker const vk::Format *AdjustViewFormatForSampler(vk::Renderer *renderer,
308*8975f5c5SAndroid Build Coastguard Worker const vk::Format *intended,
309*8975f5c5SAndroid Build Coastguard Worker gl::SamplerFormat samplerFormat)
310*8975f5c5SAndroid Build Coastguard Worker {
311*8975f5c5SAndroid Build Coastguard Worker switch (samplerFormat)
312*8975f5c5SAndroid Build Coastguard Worker {
313*8975f5c5SAndroid Build Coastguard Worker case gl::SamplerFormat::Float:
314*8975f5c5SAndroid Build Coastguard Worker switch (intended->getIntendedFormatID())
315*8975f5c5SAndroid Build Coastguard Worker {
316*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_UNORM:
317*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_FLOAT:
318*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_FLOAT:
319*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_UNORM:
320*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_FLOAT:
321*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_FLOAT:
322*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_FLOAT:
323*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_UNORM:
324*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_FLOAT:
325*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_FLOAT:
326*8975f5c5SAndroid Build Coastguard Worker return intended;
327*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_SINT:
328*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_UINT:
329*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8_UNORM);
330*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_SINT:
331*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_UINT:
332*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16_FLOAT);
333*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_SINT:
334*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_UINT:
335*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32_FLOAT);
336*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_SINT:
337*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_UINT:
338*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8G8_UNORM);
339*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_SINT:
340*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_UINT:
341*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16G16_FLOAT);
342*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_SINT:
343*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_UINT:
344*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32_FLOAT);
345*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_SINT:
346*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_UINT:
347*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32B32_FLOAT);
348*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_SINT:
349*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_UINT:
350*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8G8B8A8_UNORM);
351*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_SINT:
352*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_UINT:
353*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16G16B16A16_FLOAT);
354*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_SINT:
355*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_UINT:
356*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
357*8975f5c5SAndroid Build Coastguard Worker default:
358*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
359*8975f5c5SAndroid Build Coastguard Worker return intended;
360*8975f5c5SAndroid Build Coastguard Worker }
361*8975f5c5SAndroid Build Coastguard Worker case gl::SamplerFormat::Unsigned:
362*8975f5c5SAndroid Build Coastguard Worker switch (intended->getIntendedFormatID())
363*8975f5c5SAndroid Build Coastguard Worker {
364*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_UINT:
365*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_UINT:
366*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_UINT:
367*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_UINT:
368*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_UINT:
369*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_UINT:
370*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_UINT:
371*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_UINT:
372*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_UINT:
373*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_UINT:
374*8975f5c5SAndroid Build Coastguard Worker return intended;
375*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_UNORM:
376*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_SINT:
377*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8_UINT);
378*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_FLOAT:
379*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_SINT:
380*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16_UINT);
381*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_FLOAT:
382*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_SINT:
383*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32_UINT);
384*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_UNORM:
385*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_SINT:
386*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8G8_UINT);
387*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_FLOAT:
388*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_SINT:
389*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16G16_UINT);
390*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_FLOAT:
391*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_SINT:
392*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32_UINT);
393*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_FLOAT:
394*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_SINT:
395*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32B32_UINT);
396*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_UNORM:
397*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_SINT:
398*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8G8B8A8_UINT);
399*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_FLOAT:
400*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_SINT:
401*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16G16B16A16_UINT);
402*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_FLOAT:
403*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_SINT:
404*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32B32A32_UINT);
405*8975f5c5SAndroid Build Coastguard Worker default:
406*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
407*8975f5c5SAndroid Build Coastguard Worker return intended;
408*8975f5c5SAndroid Build Coastguard Worker }
409*8975f5c5SAndroid Build Coastguard Worker case gl::SamplerFormat::Signed:
410*8975f5c5SAndroid Build Coastguard Worker switch (intended->getIntendedFormatID())
411*8975f5c5SAndroid Build Coastguard Worker {
412*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_SINT:
413*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_SINT:
414*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_SINT:
415*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_SINT:
416*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_SINT:
417*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_SINT:
418*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_SINT:
419*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_SINT:
420*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_SINT:
421*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_SINT:
422*8975f5c5SAndroid Build Coastguard Worker return intended;
423*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_UNORM:
424*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8_UINT:
425*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8_SINT);
426*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_FLOAT:
427*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16_UINT:
428*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16_SINT);
429*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_FLOAT:
430*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32_UINT:
431*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32_SINT);
432*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_UNORM:
433*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8_UINT:
434*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8G8_SINT);
435*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_FLOAT:
436*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16_UINT:
437*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16G16_SINT);
438*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_FLOAT:
439*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32_UINT:
440*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32_SINT);
441*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_FLOAT:
442*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_UINT:
443*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32B32_SINT);
444*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_UNORM:
445*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R8G8B8A8_UINT:
446*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R8G8B8A8_SINT);
447*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_FLOAT:
448*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R16G16B16A16_UINT:
449*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R16G16B16A16_SINT);
450*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_FLOAT:
451*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32A32_UINT:
452*8975f5c5SAndroid Build Coastguard Worker return &renderer->getFormat(angle::FormatID::R32G32B32A32_SINT);
453*8975f5c5SAndroid Build Coastguard Worker default:
454*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
455*8975f5c5SAndroid Build Coastguard Worker return intended;
456*8975f5c5SAndroid Build Coastguard Worker }
457*8975f5c5SAndroid Build Coastguard Worker default:
458*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
459*8975f5c5SAndroid Build Coastguard Worker return intended;
460*8975f5c5SAndroid Build Coastguard Worker }
461*8975f5c5SAndroid Build Coastguard Worker }
462*8975f5c5SAndroid Build Coastguard Worker
GetRGBAEmulationDstFormat(angle::FormatID srcFormatID)463*8975f5c5SAndroid Build Coastguard Worker angle::FormatID GetRGBAEmulationDstFormat(angle::FormatID srcFormatID)
464*8975f5c5SAndroid Build Coastguard Worker {
465*8975f5c5SAndroid Build Coastguard Worker switch (srcFormatID)
466*8975f5c5SAndroid Build Coastguard Worker {
467*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_UINT:
468*8975f5c5SAndroid Build Coastguard Worker return angle::FormatID::R32G32B32A32_UINT;
469*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_SINT:
470*8975f5c5SAndroid Build Coastguard Worker return angle::FormatID::R32G32B32A32_SINT;
471*8975f5c5SAndroid Build Coastguard Worker case angle::FormatID::R32G32B32_FLOAT:
472*8975f5c5SAndroid Build Coastguard Worker return angle::FormatID::R32G32B32A32_FLOAT;
473*8975f5c5SAndroid Build Coastguard Worker default:
474*8975f5c5SAndroid Build Coastguard Worker return angle::FormatID::NONE;
475*8975f5c5SAndroid Build Coastguard Worker }
476*8975f5c5SAndroid Build Coastguard Worker }
477*8975f5c5SAndroid Build Coastguard Worker
NeedsRGBAEmulation(vk::Renderer * renderer,angle::FormatID formatID)478*8975f5c5SAndroid Build Coastguard Worker bool NeedsRGBAEmulation(vk::Renderer *renderer, angle::FormatID formatID)
479*8975f5c5SAndroid Build Coastguard Worker {
480*8975f5c5SAndroid Build Coastguard Worker if (renderer->hasBufferFormatFeatureBits(formatID, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
481*8975f5c5SAndroid Build Coastguard Worker {
482*8975f5c5SAndroid Build Coastguard Worker return false;
483*8975f5c5SAndroid Build Coastguard Worker }
484*8975f5c5SAndroid Build Coastguard Worker // Vulkan driver support is required for all formats except the ones we emulate.
485*8975f5c5SAndroid Build Coastguard Worker ASSERT(GetRGBAEmulationDstFormat(formatID) != angle::FormatID::NONE);
486*8975f5c5SAndroid Build Coastguard Worker return true;
487*8975f5c5SAndroid Build Coastguard Worker }
488*8975f5c5SAndroid Build Coastguard Worker
489*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
490*8975f5c5SAndroid Build Coastguard Worker
491*8975f5c5SAndroid Build Coastguard Worker // TextureVk implementation.
TextureVk(const gl::TextureState & state,vk::Renderer * renderer)492*8975f5c5SAndroid Build Coastguard Worker TextureVk::TextureVk(const gl::TextureState &state, vk::Renderer *renderer)
493*8975f5c5SAndroid Build Coastguard Worker : TextureImpl(state),
494*8975f5c5SAndroid Build Coastguard Worker mOwnsImage(false),
495*8975f5c5SAndroid Build Coastguard Worker mRequiresMutableStorage(false),
496*8975f5c5SAndroid Build Coastguard Worker mRequiredImageAccess(vk::ImageAccess::SampleOnly),
497*8975f5c5SAndroid Build Coastguard Worker mImmutableSamplerDirty(false),
498*8975f5c5SAndroid Build Coastguard Worker mEGLImageNativeType(gl::TextureType::InvalidEnum),
499*8975f5c5SAndroid Build Coastguard Worker mEGLImageLayerOffset(0),
500*8975f5c5SAndroid Build Coastguard Worker mEGLImageLevelOffset(0),
501*8975f5c5SAndroid Build Coastguard Worker mImage(nullptr),
502*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags(0),
503*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags(0),
504*8975f5c5SAndroid Build Coastguard Worker mImageObserverBinding(this, kTextureImageSubjectIndex),
505*8975f5c5SAndroid Build Coastguard Worker mCurrentBaseLevel(state.getBaseLevel()),
506*8975f5c5SAndroid Build Coastguard Worker mCurrentMaxLevel(state.getMaxLevel()),
507*8975f5c5SAndroid Build Coastguard Worker mCachedImageViewSubresourceSerialSRGBDecode{},
508*8975f5c5SAndroid Build Coastguard Worker mCachedImageViewSubresourceSerialSkipDecode{}
509*8975f5c5SAndroid Build Coastguard Worker {}
510*8975f5c5SAndroid Build Coastguard Worker
511*8975f5c5SAndroid Build Coastguard Worker TextureVk::~TextureVk() = default;
512*8975f5c5SAndroid Build Coastguard Worker
onDestroy(const gl::Context * context)513*8975f5c5SAndroid Build Coastguard Worker void TextureVk::onDestroy(const gl::Context *context)
514*8975f5c5SAndroid Build Coastguard Worker {
515*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
516*8975f5c5SAndroid Build Coastguard Worker
517*8975f5c5SAndroid Build Coastguard Worker releaseAndDeleteImageAndViews(contextVk);
518*8975f5c5SAndroid Build Coastguard Worker resetSampler();
519*8975f5c5SAndroid Build Coastguard Worker }
520*8975f5c5SAndroid Build Coastguard Worker
setImage(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,const gl::Extents & size,GLenum format,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels)521*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setImage(const gl::Context *context,
522*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
523*8975f5c5SAndroid Build Coastguard Worker GLenum internalFormat,
524*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size,
525*8975f5c5SAndroid Build Coastguard Worker GLenum format,
526*8975f5c5SAndroid Build Coastguard Worker GLenum type,
527*8975f5c5SAndroid Build Coastguard Worker const gl::PixelUnpackState &unpack,
528*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *unpackBuffer,
529*8975f5c5SAndroid Build Coastguard Worker const uint8_t *pixels)
530*8975f5c5SAndroid Build Coastguard Worker {
531*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
532*8975f5c5SAndroid Build Coastguard Worker
533*8975f5c5SAndroid Build Coastguard Worker return setImageImpl(context, index, formatInfo, size, type, unpack, unpackBuffer, pixels);
534*8975f5c5SAndroid Build Coastguard Worker }
535*8975f5c5SAndroid Build Coastguard Worker
setSubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Box & area,GLenum format,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels)536*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setSubImage(const gl::Context *context,
537*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
538*8975f5c5SAndroid Build Coastguard Worker const gl::Box &area,
539*8975f5c5SAndroid Build Coastguard Worker GLenum format,
540*8975f5c5SAndroid Build Coastguard Worker GLenum type,
541*8975f5c5SAndroid Build Coastguard Worker const gl::PixelUnpackState &unpack,
542*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *unpackBuffer,
543*8975f5c5SAndroid Build Coastguard Worker const uint8_t *pixels)
544*8975f5c5SAndroid Build Coastguard Worker {
545*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
546*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
547*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &levelDesc = mState.getImageDesc(index);
548*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat =
549*8975f5c5SAndroid Build Coastguard Worker contextVk->getRenderer()->getFormat(levelDesc.format.info->sizedInternalFormat);
550*8975f5c5SAndroid Build Coastguard Worker
551*8975f5c5SAndroid Build Coastguard Worker return setSubImageImpl(context, index, area, formatInfo, type, unpack, unpackBuffer, pixels,
552*8975f5c5SAndroid Build Coastguard Worker vkFormat);
553*8975f5c5SAndroid Build Coastguard Worker }
554*8975f5c5SAndroid Build Coastguard Worker
isCompressedFormatEmulated(const gl::Context * context,gl::TextureTarget target,GLint level)555*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::isCompressedFormatEmulated(const gl::Context *context,
556*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget target,
557*8975f5c5SAndroid Build Coastguard Worker GLint level)
558*8975f5c5SAndroid Build Coastguard Worker {
559*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &levelDesc = mState.getImageDesc(target, level);
560*8975f5c5SAndroid Build Coastguard Worker if (!levelDesc.format.info->compressed)
561*8975f5c5SAndroid Build Coastguard Worker {
562*8975f5c5SAndroid Build Coastguard Worker // If it isn't compressed, the remaining logic won't work
563*8975f5c5SAndroid Build Coastguard Worker return false;
564*8975f5c5SAndroid Build Coastguard Worker }
565*8975f5c5SAndroid Build Coastguard Worker
566*8975f5c5SAndroid Build Coastguard Worker // Check against the list of formats used to emulate compressed textures
567*8975f5c5SAndroid Build Coastguard Worker return gl::IsEmulatedCompressedFormat(levelDesc.format.info->sizedInternalFormat);
568*8975f5c5SAndroid Build Coastguard Worker }
569*8975f5c5SAndroid Build Coastguard Worker
setCompressedImage(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,const gl::Extents & size,const gl::PixelUnpackState & unpack,size_t imageSize,const uint8_t * pixels)570*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setCompressedImage(const gl::Context *context,
571*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
572*8975f5c5SAndroid Build Coastguard Worker GLenum internalFormat,
573*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size,
574*8975f5c5SAndroid Build Coastguard Worker const gl::PixelUnpackState &unpack,
575*8975f5c5SAndroid Build Coastguard Worker size_t imageSize,
576*8975f5c5SAndroid Build Coastguard Worker const uint8_t *pixels)
577*8975f5c5SAndroid Build Coastguard Worker {
578*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
579*8975f5c5SAndroid Build Coastguard Worker
580*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = context->getState();
581*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *unpackBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
582*8975f5c5SAndroid Build Coastguard Worker
583*8975f5c5SAndroid Build Coastguard Worker if (unpackBuffer &&
584*8975f5c5SAndroid Build Coastguard Worker this->isCompressedFormatEmulated(context, index.getTarget(), index.getLevelIndex()))
585*8975f5c5SAndroid Build Coastguard Worker {
586*8975f5c5SAndroid Build Coastguard Worker // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
587*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
588*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop;
589*8975f5c5SAndroid Build Coastguard Worker }
590*8975f5c5SAndroid Build Coastguard Worker
591*8975f5c5SAndroid Build Coastguard Worker return setImageImpl(context, index, formatInfo, size, GL_UNSIGNED_BYTE, unpack, unpackBuffer,
592*8975f5c5SAndroid Build Coastguard Worker pixels);
593*8975f5c5SAndroid Build Coastguard Worker }
594*8975f5c5SAndroid Build Coastguard Worker
setCompressedSubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Box & area,GLenum format,const gl::PixelUnpackState & unpack,size_t imageSize,const uint8_t * pixels)595*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setCompressedSubImage(const gl::Context *context,
596*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
597*8975f5c5SAndroid Build Coastguard Worker const gl::Box &area,
598*8975f5c5SAndroid Build Coastguard Worker GLenum format,
599*8975f5c5SAndroid Build Coastguard Worker const gl::PixelUnpackState &unpack,
600*8975f5c5SAndroid Build Coastguard Worker size_t imageSize,
601*8975f5c5SAndroid Build Coastguard Worker const uint8_t *pixels)
602*8975f5c5SAndroid Build Coastguard Worker {
603*8975f5c5SAndroid Build Coastguard Worker
604*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, GL_UNSIGNED_BYTE);
605*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
606*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &levelDesc = mState.getImageDesc(index);
607*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat =
608*8975f5c5SAndroid Build Coastguard Worker contextVk->getRenderer()->getFormat(levelDesc.format.info->sizedInternalFormat);
609*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = contextVk->getState();
610*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *unpackBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
611*8975f5c5SAndroid Build Coastguard Worker
612*8975f5c5SAndroid Build Coastguard Worker if (unpackBuffer &&
613*8975f5c5SAndroid Build Coastguard Worker this->isCompressedFormatEmulated(context, index.getTarget(), index.getLevelIndex()))
614*8975f5c5SAndroid Build Coastguard Worker {
615*8975f5c5SAndroid Build Coastguard Worker // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
616*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
617*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop;
618*8975f5c5SAndroid Build Coastguard Worker }
619*8975f5c5SAndroid Build Coastguard Worker
620*8975f5c5SAndroid Build Coastguard Worker return setSubImageImpl(context, index, area, formatInfo, GL_UNSIGNED_BYTE, unpack, unpackBuffer,
621*8975f5c5SAndroid Build Coastguard Worker pixels, vkFormat);
622*8975f5c5SAndroid Build Coastguard Worker }
623*8975f5c5SAndroid Build Coastguard Worker
setImageImpl(const gl::Context * context,const gl::ImageIndex & index,const gl::InternalFormat & formatInfo,const gl::Extents & size,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels)624*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setImageImpl(const gl::Context *context,
625*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
626*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &formatInfo,
627*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size,
628*8975f5c5SAndroid Build Coastguard Worker GLenum type,
629*8975f5c5SAndroid Build Coastguard Worker const gl::PixelUnpackState &unpack,
630*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *unpackBuffer,
631*8975f5c5SAndroid Build Coastguard Worker const uint8_t *pixels)
632*8975f5c5SAndroid Build Coastguard Worker {
633*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
634*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
635*8975f5c5SAndroid Build Coastguard Worker
636*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
637*8975f5c5SAndroid Build Coastguard Worker
638*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(redefineLevel(context, index, vkFormat, size));
639*8975f5c5SAndroid Build Coastguard Worker
640*8975f5c5SAndroid Build Coastguard Worker // Early-out on empty textures, don't create a zero-sized storage.
641*8975f5c5SAndroid Build Coastguard Worker if (size.empty())
642*8975f5c5SAndroid Build Coastguard Worker {
643*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
644*8975f5c5SAndroid Build Coastguard Worker }
645*8975f5c5SAndroid Build Coastguard Worker
646*8975f5c5SAndroid Build Coastguard Worker return setSubImageImpl(context, index, gl::Box(gl::kOffsetZero, size), formatInfo, type, unpack,
647*8975f5c5SAndroid Build Coastguard Worker unpackBuffer, pixels, vkFormat);
648*8975f5c5SAndroid Build Coastguard Worker }
649*8975f5c5SAndroid Build Coastguard Worker
isFastUnpackPossible(const vk::Format & vkFormat,size_t offset,const vk::Format & bufferVkFormat) const650*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::isFastUnpackPossible(const vk::Format &vkFormat,
651*8975f5c5SAndroid Build Coastguard Worker size_t offset,
652*8975f5c5SAndroid Build Coastguard Worker const vk::Format &bufferVkFormat) const
653*8975f5c5SAndroid Build Coastguard Worker {
654*8975f5c5SAndroid Build Coastguard Worker // Conditions to determine if fast unpacking is possible
655*8975f5c5SAndroid Build Coastguard Worker // 1. Image must be well defined to unpack directly to it
656*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42262852) Create and stage a temp image instead
657*8975f5c5SAndroid Build Coastguard Worker // 2. Can't perform a fast copy for depth/stencil, except from non-emulated depth or stencil
658*8975f5c5SAndroid Build Coastguard Worker // to emulated depth/stencil. GL requires depth and stencil data to be packed, while Vulkan
659*8975f5c5SAndroid Build Coastguard Worker // requires them to be separate.
660*8975f5c5SAndroid Build Coastguard Worker // 3. Can't perform a fast copy for emulated formats, except from non-emulated depth or stencil
661*8975f5c5SAndroid Build Coastguard Worker // to emulated depth/stencil.
662*8975f5c5SAndroid Build Coastguard Worker // 4. vkCmdCopyBufferToImage requires byte offset to be a multiple of 4.
663*8975f5c5SAndroid Build Coastguard Worker // 5. Actual texture format and intended buffer format must match for color formats
664*8975f5c5SAndroid Build Coastguard Worker const angle::Format &bufferFormat = vkFormat.getActualBufferFormat(false);
665*8975f5c5SAndroid Build Coastguard Worker const bool isCombinedDepthStencil = bufferFormat.hasDepthAndStencilBits();
666*8975f5c5SAndroid Build Coastguard Worker const bool isDepthXorStencil = bufferFormat.hasDepthOrStencilBits() && !isCombinedDepthStencil;
667*8975f5c5SAndroid Build Coastguard Worker const bool isCompatibleDepth = vkFormat.getIntendedFormat().depthBits == bufferFormat.depthBits;
668*8975f5c5SAndroid Build Coastguard Worker const VkDeviceSize imageCopyAlignment =
669*8975f5c5SAndroid Build Coastguard Worker vk::GetImageCopyBufferAlignment(mImage->getActualFormatID());
670*8975f5c5SAndroid Build Coastguard Worker const bool formatsMatch = bufferFormat.hasDepthOrStencilBits() ||
671*8975f5c5SAndroid Build Coastguard Worker (vkFormat.getActualImageFormatID(getRequiredImageAccess()) ==
672*8975f5c5SAndroid Build Coastguard Worker bufferVkFormat.getIntendedFormatID());
673*8975f5c5SAndroid Build Coastguard Worker
674*8975f5c5SAndroid Build Coastguard Worker return mImage->valid() && !isCombinedDepthStencil &&
675*8975f5c5SAndroid Build Coastguard Worker (vkFormat.getIntendedFormatID() ==
676*8975f5c5SAndroid Build Coastguard Worker vkFormat.getActualImageFormatID(getRequiredImageAccess()) ||
677*8975f5c5SAndroid Build Coastguard Worker (isDepthXorStencil && isCompatibleDepth)) &&
678*8975f5c5SAndroid Build Coastguard Worker (offset % imageCopyAlignment) == 0 && formatsMatch;
679*8975f5c5SAndroid Build Coastguard Worker }
680*8975f5c5SAndroid Build Coastguard Worker
isMipImageDescDefined(gl::TextureTarget textureTarget,size_t level)681*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::isMipImageDescDefined(gl::TextureTarget textureTarget, size_t level)
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker // A defined image should have defined width, height, and format.
684*8975f5c5SAndroid Build Coastguard Worker gl::ImageDesc imageDesc = mState.getImageDesc(textureTarget, level);
685*8975f5c5SAndroid Build Coastguard Worker return imageDesc.size.height != 0 && imageDesc.size.width != 0 &&
686*8975f5c5SAndroid Build Coastguard Worker imageDesc.format.info->format != GL_NONE;
687*8975f5c5SAndroid Build Coastguard Worker }
688*8975f5c5SAndroid Build Coastguard Worker
isMutableTextureConsistentlySpecifiedForFlush()689*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::isMutableTextureConsistentlySpecifiedForFlush()
690*8975f5c5SAndroid Build Coastguard Worker {
691*8975f5c5SAndroid Build Coastguard Worker // Disable optimization if the base level is not 0.
692*8975f5c5SAndroid Build Coastguard Worker if (mState.getBaseLevel() != 0)
693*8975f5c5SAndroid Build Coastguard Worker {
694*8975f5c5SAndroid Build Coastguard Worker return false;
695*8975f5c5SAndroid Build Coastguard Worker }
696*8975f5c5SAndroid Build Coastguard Worker
697*8975f5c5SAndroid Build Coastguard Worker // If the texture is a cubemap, we will have to wait until it is complete.
698*8975f5c5SAndroid Build Coastguard Worker if (mState.getType() == gl::TextureType::CubeMap && !mState.isCubeComplete())
699*8975f5c5SAndroid Build Coastguard Worker {
700*8975f5c5SAndroid Build Coastguard Worker return false;
701*8975f5c5SAndroid Build Coastguard Worker }
702*8975f5c5SAndroid Build Coastguard Worker
703*8975f5c5SAndroid Build Coastguard Worker // Before we initialize the mips, we make sure that the base mip level is properly defined.
704*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget textureTarget = (mState.getType() == gl::TextureType::CubeMap)
705*8975f5c5SAndroid Build Coastguard Worker ? gl::kCubeMapTextureTargetMin
706*8975f5c5SAndroid Build Coastguard Worker : gl::TextureTypeToTarget(mState.getType(), 0);
707*8975f5c5SAndroid Build Coastguard Worker if (!isMipImageDescDefined(textureTarget, 0))
708*8975f5c5SAndroid Build Coastguard Worker {
709*8975f5c5SAndroid Build Coastguard Worker return false;
710*8975f5c5SAndroid Build Coastguard Worker }
711*8975f5c5SAndroid Build Coastguard Worker
712*8975f5c5SAndroid Build Coastguard Worker // We do not flush if the texture has been bound as an attachment.
713*8975f5c5SAndroid Build Coastguard Worker if (mState.hasBeenBoundAsAttachment())
714*8975f5c5SAndroid Build Coastguard Worker {
715*8975f5c5SAndroid Build Coastguard Worker return false;
716*8975f5c5SAndroid Build Coastguard Worker }
717*8975f5c5SAndroid Build Coastguard Worker
718*8975f5c5SAndroid Build Coastguard Worker // For performance, flushing is skipped if the number of staged updates in a mip level is not
719*8975f5c5SAndroid Build Coastguard Worker // one. For a cubemap, this applies to each face of the cube instead.
720*8975f5c5SAndroid Build Coastguard Worker size_t maxUpdatesPerMipLevel = (mState.getType() == gl::TextureType::CubeMap) ? 6 : 1;
721*8975f5c5SAndroid Build Coastguard Worker if (mImage->getLevelUpdateCount(gl::LevelIndex(0)) != maxUpdatesPerMipLevel)
722*8975f5c5SAndroid Build Coastguard Worker {
723*8975f5c5SAndroid Build Coastguard Worker return false;
724*8975f5c5SAndroid Build Coastguard Worker }
725*8975f5c5SAndroid Build Coastguard Worker
726*8975f5c5SAndroid Build Coastguard Worker // The mip levels that are already defined should have attributes compatible with those of the
727*8975f5c5SAndroid Build Coastguard Worker // base mip level. For each defined mip level, its size, format, number of samples, and depth
728*8975f5c5SAndroid Build Coastguard Worker // are checked before flushing the texture updates. For complete cubemaps, there are 6 images
729*8975f5c5SAndroid Build Coastguard Worker // per mip level. Therefore, mState would have 6 times as many images.
730*8975f5c5SAndroid Build Coastguard Worker gl::ImageDesc baseImageDesc = mState.getImageDesc(textureTarget, 0);
731*8975f5c5SAndroid Build Coastguard Worker size_t maxImageMipLevels = (mState.getType() == gl::TextureType::CubeMap)
732*8975f5c5SAndroid Build Coastguard Worker ? (mState.getImageDescs().size() / 6)
733*8975f5c5SAndroid Build Coastguard Worker : mState.getImageDescs().size();
734*8975f5c5SAndroid Build Coastguard Worker
735*8975f5c5SAndroid Build Coastguard Worker for (size_t image = 1; image < maxImageMipLevels; image++)
736*8975f5c5SAndroid Build Coastguard Worker {
737*8975f5c5SAndroid Build Coastguard Worker gl::ImageDesc mipImageDesc = mState.getImageDesc(textureTarget, image);
738*8975f5c5SAndroid Build Coastguard Worker if (!isMipImageDescDefined(textureTarget, image))
739*8975f5c5SAndroid Build Coastguard Worker {
740*8975f5c5SAndroid Build Coastguard Worker continue;
741*8975f5c5SAndroid Build Coastguard Worker }
742*8975f5c5SAndroid Build Coastguard Worker
743*8975f5c5SAndroid Build Coastguard Worker // If the texture is 2DArray or 3D, the depths should also be checked according to the mip
744*8975f5c5SAndroid Build Coastguard Worker // levels. If the texture type is a cube map array, the depth represents the number of
745*8975f5c5SAndroid Build Coastguard Worker // layer-faces and does not change for mipmaps. Otherwise, we skip the depth comparison.
746*8975f5c5SAndroid Build Coastguard Worker gl::Extents baseImageDescMipSize;
747*8975f5c5SAndroid Build Coastguard Worker baseImageDescMipSize.width = std::max(baseImageDesc.size.width >> image, 1);
748*8975f5c5SAndroid Build Coastguard Worker baseImageDescMipSize.height = std::max(baseImageDesc.size.height >> image, 1);
749*8975f5c5SAndroid Build Coastguard Worker baseImageDescMipSize.depth = std::max(baseImageDesc.size.depth >> image, 1);
750*8975f5c5SAndroid Build Coastguard Worker
751*8975f5c5SAndroid Build Coastguard Worker bool isDepthCompatible = (mState.getType() == gl::TextureType::_3D ||
752*8975f5c5SAndroid Build Coastguard Worker mState.getType() == gl::TextureType::_2DArray)
753*8975f5c5SAndroid Build Coastguard Worker ? (baseImageDescMipSize.depth == mipImageDesc.size.depth)
754*8975f5c5SAndroid Build Coastguard Worker : (mState.getType() != gl::TextureType::CubeMapArray ||
755*8975f5c5SAndroid Build Coastguard Worker baseImageDesc.size.depth == mipImageDesc.size.depth);
756*8975f5c5SAndroid Build Coastguard Worker
757*8975f5c5SAndroid Build Coastguard Worker bool isSizeCompatible = (baseImageDescMipSize.width == mipImageDesc.size.width) &&
758*8975f5c5SAndroid Build Coastguard Worker (baseImageDescMipSize.height == mipImageDesc.size.height) &&
759*8975f5c5SAndroid Build Coastguard Worker isDepthCompatible;
760*8975f5c5SAndroid Build Coastguard Worker bool isFormatCompatible = (baseImageDesc.format.info->sizedInternalFormat ==
761*8975f5c5SAndroid Build Coastguard Worker mipImageDesc.format.info->sizedInternalFormat);
762*8975f5c5SAndroid Build Coastguard Worker bool isNumberOfSamplesCompatible = (baseImageDesc.samples == mipImageDesc.samples);
763*8975f5c5SAndroid Build Coastguard Worker
764*8975f5c5SAndroid Build Coastguard Worker bool isUpdateCompatible =
765*8975f5c5SAndroid Build Coastguard Worker (mImage->getLevelUpdateCount(gl::LevelIndex(static_cast<GLint>(image))) ==
766*8975f5c5SAndroid Build Coastguard Worker maxUpdatesPerMipLevel);
767*8975f5c5SAndroid Build Coastguard Worker
768*8975f5c5SAndroid Build Coastguard Worker if (!isSizeCompatible || !isFormatCompatible || !isNumberOfSamplesCompatible ||
769*8975f5c5SAndroid Build Coastguard Worker !isUpdateCompatible)
770*8975f5c5SAndroid Build Coastguard Worker {
771*8975f5c5SAndroid Build Coastguard Worker return false;
772*8975f5c5SAndroid Build Coastguard Worker }
773*8975f5c5SAndroid Build Coastguard Worker }
774*8975f5c5SAndroid Build Coastguard Worker
775*8975f5c5SAndroid Build Coastguard Worker return true;
776*8975f5c5SAndroid Build Coastguard Worker }
777*8975f5c5SAndroid Build Coastguard Worker
updateMustBeFlushed(gl::LevelIndex textureLevelIndexGL,angle::FormatID dstImageFormatID) const778*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::updateMustBeFlushed(gl::LevelIndex textureLevelIndexGL,
779*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstImageFormatID) const
780*8975f5c5SAndroid Build Coastguard Worker {
781*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage);
782*8975f5c5SAndroid Build Coastguard Worker
783*8975f5c5SAndroid Build Coastguard Worker // For EGLImages we should never stage the update since staged update is subject to thread
784*8975f5c5SAndroid Build Coastguard Worker // racing bugs when two textures in different share groups are accessed at same time.
785*8975f5c5SAndroid Build Coastguard Worker if (!mOwnsImage)
786*8975f5c5SAndroid Build Coastguard Worker {
787*8975f5c5SAndroid Build Coastguard Worker // EGLImage is always initialized upon creation and format should always renderable so that
788*8975f5c5SAndroid Build Coastguard Worker // there is no format upgrade.
789*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->valid());
790*8975f5c5SAndroid Build Coastguard Worker ASSERT(IsTextureLevelInAllocatedImage(*mImage, textureLevelIndexGL));
791*8975f5c5SAndroid Build Coastguard Worker ASSERT(!IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), textureLevelIndexGL));
792*8975f5c5SAndroid Build Coastguard Worker return true;
793*8975f5c5SAndroid Build Coastguard Worker }
794*8975f5c5SAndroid Build Coastguard Worker return false;
795*8975f5c5SAndroid Build Coastguard Worker }
796*8975f5c5SAndroid Build Coastguard Worker
updateMustBeStaged(gl::LevelIndex textureLevelIndexGL,angle::FormatID dstImageFormatID) const797*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::updateMustBeStaged(gl::LevelIndex textureLevelIndexGL,
798*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstImageFormatID) const
799*8975f5c5SAndroid Build Coastguard Worker {
800*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage);
801*8975f5c5SAndroid Build Coastguard Worker
802*8975f5c5SAndroid Build Coastguard Worker // If we do not have storage yet, there is impossible to immediately do the copy, so just
803*8975f5c5SAndroid Build Coastguard Worker // stage it. Note that immutable texture will have a valid storage.
804*8975f5c5SAndroid Build Coastguard Worker if (!mImage->valid())
805*8975f5c5SAndroid Build Coastguard Worker {
806*8975f5c5SAndroid Build Coastguard Worker return true;
807*8975f5c5SAndroid Build Coastguard Worker }
808*8975f5c5SAndroid Build Coastguard Worker
809*8975f5c5SAndroid Build Coastguard Worker // If update is outside the range of image levels, it must be staged.
810*8975f5c5SAndroid Build Coastguard Worker if (!IsTextureLevelInAllocatedImage(*mImage, textureLevelIndexGL))
811*8975f5c5SAndroid Build Coastguard Worker {
812*8975f5c5SAndroid Build Coastguard Worker return true;
813*8975f5c5SAndroid Build Coastguard Worker }
814*8975f5c5SAndroid Build Coastguard Worker
815*8975f5c5SAndroid Build Coastguard Worker // During the process of format change, mImage's format may become stale. In that case, we
816*8975f5c5SAndroid Build Coastguard Worker // must always stage the update and let caller properly release mImage and initExternal and
817*8975f5c5SAndroid Build Coastguard Worker // flush the update.
818*8975f5c5SAndroid Build Coastguard Worker if (mImage->getActualFormatID() != dstImageFormatID)
819*8975f5c5SAndroid Build Coastguard Worker {
820*8975f5c5SAndroid Build Coastguard Worker return true;
821*8975f5c5SAndroid Build Coastguard Worker }
822*8975f5c5SAndroid Build Coastguard Worker
823*8975f5c5SAndroid Build Coastguard Worker // Otherwise, it can only be directly applied to the image if the level is not previously
824*8975f5c5SAndroid Build Coastguard Worker // incompatibly redefined.
825*8975f5c5SAndroid Build Coastguard Worker return IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), textureLevelIndexGL);
826*8975f5c5SAndroid Build Coastguard Worker }
827*8975f5c5SAndroid Build Coastguard Worker
clearImage(const gl::Context * context,GLint level,GLenum format,GLenum type,const uint8_t * data)828*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::clearImage(const gl::Context *context,
829*8975f5c5SAndroid Build Coastguard Worker GLint level,
830*8975f5c5SAndroid Build Coastguard Worker GLenum format,
831*8975f5c5SAndroid Build Coastguard Worker GLenum type,
832*8975f5c5SAndroid Build Coastguard Worker const uint8_t *data)
833*8975f5c5SAndroid Build Coastguard Worker {
834*8975f5c5SAndroid Build Coastguard Worker // All defined cubemap faces are expected to have equal width and height.
835*8975f5c5SAndroid Build Coastguard Worker bool isCubeMap = mState.getType() == gl::TextureType::CubeMap;
836*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget textureTarget =
837*8975f5c5SAndroid Build Coastguard Worker isCubeMap ? gl::kCubeMapTextureTargetMin : gl::TextureTypeToTarget(mState.getType(), 0);
838*8975f5c5SAndroid Build Coastguard Worker gl::Extents extents = mState.getImageDesc(textureTarget, level).size;
839*8975f5c5SAndroid Build Coastguard Worker
840*8975f5c5SAndroid Build Coastguard Worker gl::Box area = gl::Box(gl::kOffsetZero, extents);
841*8975f5c5SAndroid Build Coastguard Worker if (isCubeMap)
842*8975f5c5SAndroid Build Coastguard Worker {
843*8975f5c5SAndroid Build Coastguard Worker // For a cubemap, the depth offset moves between cube faces.
844*8975f5c5SAndroid Build Coastguard Worker ASSERT(area.depth == 1);
845*8975f5c5SAndroid Build Coastguard Worker area.depth = 6;
846*8975f5c5SAndroid Build Coastguard Worker }
847*8975f5c5SAndroid Build Coastguard Worker
848*8975f5c5SAndroid Build Coastguard Worker return clearSubImageImpl(context, level, area, vk::ClearTextureMode::FullClear, format, type,
849*8975f5c5SAndroid Build Coastguard Worker data);
850*8975f5c5SAndroid Build Coastguard Worker }
851*8975f5c5SAndroid Build Coastguard Worker
clearSubImage(const gl::Context * context,GLint level,const gl::Box & area,GLenum format,GLenum type,const uint8_t * data)852*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::clearSubImage(const gl::Context *context,
853*8975f5c5SAndroid Build Coastguard Worker GLint level,
854*8975f5c5SAndroid Build Coastguard Worker const gl::Box &area,
855*8975f5c5SAndroid Build Coastguard Worker GLenum format,
856*8975f5c5SAndroid Build Coastguard Worker GLenum type,
857*8975f5c5SAndroid Build Coastguard Worker const uint8_t *data)
858*8975f5c5SAndroid Build Coastguard Worker {
859*8975f5c5SAndroid Build Coastguard Worker bool isCubeMap = mState.getType() == gl::TextureType::CubeMap;
860*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget textureTarget =
861*8975f5c5SAndroid Build Coastguard Worker isCubeMap ? gl::kCubeMapTextureTargetMin : gl::TextureTypeToTarget(mState.getType(), 0);
862*8975f5c5SAndroid Build Coastguard Worker gl::Extents extents = mState.getImageDesc(textureTarget, level).size;
863*8975f5c5SAndroid Build Coastguard Worker int depthForFullClear = isCubeMap ? 6 : extents.depth;
864*8975f5c5SAndroid Build Coastguard Worker
865*8975f5c5SAndroid Build Coastguard Worker vk::ClearTextureMode clearMode = vk::ClearTextureMode::PartialClear;
866*8975f5c5SAndroid Build Coastguard Worker if (extents.width == area.width && extents.height == area.height &&
867*8975f5c5SAndroid Build Coastguard Worker depthForFullClear == area.depth)
868*8975f5c5SAndroid Build Coastguard Worker {
869*8975f5c5SAndroid Build Coastguard Worker clearMode = vk::ClearTextureMode::FullClear;
870*8975f5c5SAndroid Build Coastguard Worker }
871*8975f5c5SAndroid Build Coastguard Worker
872*8975f5c5SAndroid Build Coastguard Worker return clearSubImageImpl(context, level, area, clearMode, format, type, data);
873*8975f5c5SAndroid Build Coastguard Worker }
874*8975f5c5SAndroid Build Coastguard Worker
clearSubImageImpl(const gl::Context * context,GLint level,const gl::Box & clearArea,vk::ClearTextureMode clearMode,GLenum format,GLenum type,const uint8_t * data)875*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::clearSubImageImpl(const gl::Context *context,
876*8975f5c5SAndroid Build Coastguard Worker GLint level,
877*8975f5c5SAndroid Build Coastguard Worker const gl::Box &clearArea,
878*8975f5c5SAndroid Build Coastguard Worker vk::ClearTextureMode clearMode,
879*8975f5c5SAndroid Build Coastguard Worker GLenum format,
880*8975f5c5SAndroid Build Coastguard Worker GLenum type,
881*8975f5c5SAndroid Build Coastguard Worker const uint8_t *data)
882*8975f5c5SAndroid Build Coastguard Worker {
883*8975f5c5SAndroid Build Coastguard Worker // There should be no zero extents in the clear area, since such calls should return before
884*8975f5c5SAndroid Build Coastguard Worker // entering the backend with no changes to the texture. For 2D textures, depth should be 1.
885*8975f5c5SAndroid Build Coastguard Worker //
886*8975f5c5SAndroid Build Coastguard Worker // From the spec: For texture types that do not have certain dimensions, this command treats
887*8975f5c5SAndroid Build Coastguard Worker // those dimensions as having a size of 1. For example, to clear a portion of a two-dimensional
888*8975f5c5SAndroid Build Coastguard Worker // texture, the application would use <zoffset> equal to zero and <depth> equal to one.
889*8975f5c5SAndroid Build Coastguard Worker ASSERT(clearArea.width != 0 && clearArea.height != 0 && clearArea.depth != 0);
890*8975f5c5SAndroid Build Coastguard Worker
891*8975f5c5SAndroid Build Coastguard Worker gl::TextureType textureType = mState.getType();
892*8975f5c5SAndroid Build Coastguard Worker bool useLayerAsDepth = textureType == gl::TextureType::CubeMap ||
893*8975f5c5SAndroid Build Coastguard Worker textureType == gl::TextureType::CubeMapArray ||
894*8975f5c5SAndroid Build Coastguard Worker textureType == gl::TextureType::_2DArray ||
895*8975f5c5SAndroid Build Coastguard Worker textureType == gl::TextureType::_2DMultisampleArray;
896*8975f5c5SAndroid Build Coastguard Worker
897*8975f5c5SAndroid Build Coastguard Worker // If the texture is renderable (including multisampled), the partial clear can be applied to
898*8975f5c5SAndroid Build Coastguard Worker // the image simply by opening/closing a render pass with LOAD_OP_CLEAR. Otherwise, a buffer can
899*8975f5c5SAndroid Build Coastguard Worker // be filled with the given pixel data on the host and staged to the image as a buffer update.
900*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
901*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
902*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat =
903*8975f5c5SAndroid Build Coastguard Worker contextVk->getRenderer()->getFormat(formatInfo.sizedInternalFormat);
904*8975f5c5SAndroid Build Coastguard Worker const angle::FormatID &actualFormatID =
905*8975f5c5SAndroid Build Coastguard Worker vkFormat.getActualImageFormatID(getRequiredImageAccess());
906*8975f5c5SAndroid Build Coastguard Worker bool usesBufferForClear = false;
907*8975f5c5SAndroid Build Coastguard Worker
908*8975f5c5SAndroid Build Coastguard Worker VkFormatFeatureFlags renderableCheckFlag =
909*8975f5c5SAndroid Build Coastguard Worker clearMode == vk::ClearTextureMode::FullClear ? VK_FORMAT_FEATURE_TRANSFER_DST_BIT
910*8975f5c5SAndroid Build Coastguard Worker : formatInfo.isDepthOrStencil() ? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
911*8975f5c5SAndroid Build Coastguard Worker : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
912*8975f5c5SAndroid Build Coastguard Worker if (vk::FormatHasNecessaryFeature(contextVk->getRenderer(), actualFormatID, getTilingMode(),
913*8975f5c5SAndroid Build Coastguard Worker renderableCheckFlag))
914*8975f5c5SAndroid Build Coastguard Worker {
915*8975f5c5SAndroid Build Coastguard Worker uint32_t baseLayer = useLayerAsDepth ? clearArea.z : 0;
916*8975f5c5SAndroid Build Coastguard Worker uint32_t layerCount = useLayerAsDepth ? clearArea.depth : 1;
917*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stagePartialClear(contextVk, clearArea, clearMode, mState.getType(),
918*8975f5c5SAndroid Build Coastguard Worker level, baseLayer, layerCount, type, formatInfo,
919*8975f5c5SAndroid Build Coastguard Worker vkFormat, getRequiredImageAccess(), data));
920*8975f5c5SAndroid Build Coastguard Worker }
921*8975f5c5SAndroid Build Coastguard Worker else
922*8975f5c5SAndroid Build Coastguard Worker {
923*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->getSamples() <= 1);
924*8975f5c5SAndroid Build Coastguard Worker bool updateAppliedImmediately = false;
925*8975f5c5SAndroid Build Coastguard Worker usesBufferForClear = true;
926*8975f5c5SAndroid Build Coastguard Worker
927*8975f5c5SAndroid Build Coastguard Worker auto pixelSize = static_cast<size_t>(formatInfo.pixelBytes);
928*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> pixelValue(pixelSize, 0);
929*8975f5c5SAndroid Build Coastguard Worker if (data != nullptr)
930*8975f5c5SAndroid Build Coastguard Worker {
931*8975f5c5SAndroid Build Coastguard Worker memcpy(pixelValue.data(), data, pixelSize);
932*8975f5c5SAndroid Build Coastguard Worker }
933*8975f5c5SAndroid Build Coastguard Worker
934*8975f5c5SAndroid Build Coastguard Worker // For a cubemap, each face will be updated separately.
935*8975f5c5SAndroid Build Coastguard Worker bool isCubeMap = textureType == gl::TextureType::CubeMap;
936*8975f5c5SAndroid Build Coastguard Worker size_t clearBufferSize =
937*8975f5c5SAndroid Build Coastguard Worker isCubeMap ? clearArea.width * clearArea.height * pixelSize
938*8975f5c5SAndroid Build Coastguard Worker : clearArea.width * clearArea.height * clearArea.depth * pixelSize;
939*8975f5c5SAndroid Build Coastguard Worker
940*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> clearBuffer(clearBufferSize, 0);
941*8975f5c5SAndroid Build Coastguard Worker ASSERT(clearBufferSize % pixelSize == 0);
942*8975f5c5SAndroid Build Coastguard Worker if (data != nullptr)
943*8975f5c5SAndroid Build Coastguard Worker {
944*8975f5c5SAndroid Build Coastguard Worker for (GLuint i = 0; i < clearBufferSize; i += pixelSize)
945*8975f5c5SAndroid Build Coastguard Worker {
946*8975f5c5SAndroid Build Coastguard Worker memcpy(&clearBuffer[i], pixelValue.data(), pixelSize);
947*8975f5c5SAndroid Build Coastguard Worker }
948*8975f5c5SAndroid Build Coastguard Worker }
949*8975f5c5SAndroid Build Coastguard Worker
950*8975f5c5SAndroid Build Coastguard Worker if (isCubeMap)
951*8975f5c5SAndroid Build Coastguard Worker {
952*8975f5c5SAndroid Build Coastguard Worker size_t cubeFaceStart = clearArea.z;
953*8975f5c5SAndroid Build Coastguard Worker auto cubeFaceEnd = static_cast<size_t>(clearArea.z + clearArea.depth);
954*8975f5c5SAndroid Build Coastguard Worker
955*8975f5c5SAndroid Build Coastguard Worker for (size_t cubeFace = cubeFaceStart; cubeFace < cubeFaceEnd; cubeFace++)
956*8975f5c5SAndroid Build Coastguard Worker {
957*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex index = gl::ImageIndex::MakeFromTarget(
958*8975f5c5SAndroid Build Coastguard Worker gl::CubeFaceIndexToTextureTarget(cubeFace), level, 0);
959*8975f5c5SAndroid Build Coastguard Worker
960*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stageSubresourceUpdate(
961*8975f5c5SAndroid Build Coastguard Worker contextVk, getNativeImageIndex(index),
962*8975f5c5SAndroid Build Coastguard Worker gl::Extents(clearArea.width, clearArea.height, 1),
963*8975f5c5SAndroid Build Coastguard Worker gl::Offset(clearArea.x, clearArea.y, 0), formatInfo,
964*8975f5c5SAndroid Build Coastguard Worker contextVk->getState().getUnpackState(), type, clearBuffer.data(), vkFormat,
965*8975f5c5SAndroid Build Coastguard Worker getRequiredImageAccess(), vk::ApplyImageUpdate::Defer,
966*8975f5c5SAndroid Build Coastguard Worker &updateAppliedImmediately));
967*8975f5c5SAndroid Build Coastguard Worker ASSERT(!updateAppliedImmediately);
968*8975f5c5SAndroid Build Coastguard Worker }
969*8975f5c5SAndroid Build Coastguard Worker }
970*8975f5c5SAndroid Build Coastguard Worker else
971*8975f5c5SAndroid Build Coastguard Worker {
972*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget textureTarget = gl::TextureTypeToTarget(textureType, 0);
973*8975f5c5SAndroid Build Coastguard Worker uint32_t layerCount = useLayerAsDepth ? clearArea.depth : 0;
974*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex index =
975*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex::MakeFromTarget(textureTarget, level, layerCount);
976*8975f5c5SAndroid Build Coastguard Worker
977*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stageSubresourceUpdate(
978*8975f5c5SAndroid Build Coastguard Worker contextVk, getNativeImageIndex(index),
979*8975f5c5SAndroid Build Coastguard Worker gl::Extents(clearArea.width, clearArea.height, clearArea.depth),
980*8975f5c5SAndroid Build Coastguard Worker gl::Offset(clearArea.x, clearArea.y, clearArea.z), formatInfo,
981*8975f5c5SAndroid Build Coastguard Worker contextVk->getState().getUnpackState(), type, clearBuffer.data(), vkFormat,
982*8975f5c5SAndroid Build Coastguard Worker getRequiredImageAccess(), vk::ApplyImageUpdate::Defer, &updateAppliedImmediately));
983*8975f5c5SAndroid Build Coastguard Worker ASSERT(!updateAppliedImmediately);
984*8975f5c5SAndroid Build Coastguard Worker }
985*8975f5c5SAndroid Build Coastguard Worker }
986*8975f5c5SAndroid Build Coastguard Worker
987*8975f5c5SAndroid Build Coastguard Worker // Flush the staged updates if needed.
988*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitializedIfUpdatesNeedStageOrFlush(contextVk, gl::LevelIndex(level),
989*8975f5c5SAndroid Build Coastguard Worker vkFormat, vk::ApplyImageUpdate::Defer,
990*8975f5c5SAndroid Build Coastguard Worker usesBufferForClear));
991*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
992*8975f5c5SAndroid Build Coastguard Worker }
993*8975f5c5SAndroid Build Coastguard Worker
ensureImageInitializedIfUpdatesNeedStageOrFlush(ContextVk * contextVk,gl::LevelIndex level,const vk::Format & vkFormat,vk::ApplyImageUpdate applyUpdate,bool usesBufferForUpdate)994*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureImageInitializedIfUpdatesNeedStageOrFlush(
995*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk,
996*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex level,
997*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat,
998*8975f5c5SAndroid Build Coastguard Worker vk::ApplyImageUpdate applyUpdate,
999*8975f5c5SAndroid Build Coastguard Worker bool usesBufferForUpdate)
1000*8975f5c5SAndroid Build Coastguard Worker {
1001*8975f5c5SAndroid Build Coastguard Worker bool mustFlush =
1002*8975f5c5SAndroid Build Coastguard Worker updateMustBeFlushed(level, vkFormat.getActualImageFormatID(getRequiredImageAccess()));
1003*8975f5c5SAndroid Build Coastguard Worker bool mustStage = applyUpdate == vk::ApplyImageUpdate::Defer;
1004*8975f5c5SAndroid Build Coastguard Worker
1005*8975f5c5SAndroid Build Coastguard Worker // If texture has all levels being specified, then do the flush immediately. This tries to avoid
1006*8975f5c5SAndroid Build Coastguard Worker // issue flush as each level is being provided which may end up flushing out the staged clear
1007*8975f5c5SAndroid Build Coastguard Worker // that otherwise might able to be removed. It also helps tracking all updates with just one
1008*8975f5c5SAndroid Build Coastguard Worker // VkEvent instead of one for each level.
1009*8975f5c5SAndroid Build Coastguard Worker if (mustFlush ||
1010*8975f5c5SAndroid Build Coastguard Worker (!mustStage && mImage->valid() && mImage->hasBufferSourcedStagedUpdatesInAllLevels()))
1011*8975f5c5SAndroid Build Coastguard Worker {
1012*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1013*8975f5c5SAndroid Build Coastguard Worker
1014*8975f5c5SAndroid Build Coastguard Worker // If forceSubmitImmutableTextureUpdates is enabled, submit the staged updates as well.
1015*8975f5c5SAndroid Build Coastguard Worker if (contextVk->getFeatures().forceSubmitImmutableTextureUpdates.enabled)
1016*8975f5c5SAndroid Build Coastguard Worker {
1017*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->submitStagedTextureUpdates());
1018*8975f5c5SAndroid Build Coastguard Worker }
1019*8975f5c5SAndroid Build Coastguard Worker }
1020*8975f5c5SAndroid Build Coastguard Worker else if (usesBufferForUpdate && contextVk->isEligibleForMutableTextureFlush() &&
1021*8975f5c5SAndroid Build Coastguard Worker !mState.getImmutableFormat())
1022*8975f5c5SAndroid Build Coastguard Worker {
1023*8975f5c5SAndroid Build Coastguard Worker // Check if we should flush any mutable textures from before.
1024*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getShareGroup()->onMutableTextureUpload(contextVk, this));
1025*8975f5c5SAndroid Build Coastguard Worker }
1026*8975f5c5SAndroid Build Coastguard Worker
1027*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1028*8975f5c5SAndroid Build Coastguard Worker }
1029*8975f5c5SAndroid Build Coastguard Worker
setSubImageImpl(const gl::Context * context,const gl::ImageIndex & index,const gl::Box & area,const gl::InternalFormat & formatInfo,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels,const vk::Format & vkFormat)1030*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setSubImageImpl(const gl::Context *context,
1031*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1032*8975f5c5SAndroid Build Coastguard Worker const gl::Box &area,
1033*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &formatInfo,
1034*8975f5c5SAndroid Build Coastguard Worker GLenum type,
1035*8975f5c5SAndroid Build Coastguard Worker const gl::PixelUnpackState &unpack,
1036*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *unpackBuffer,
1037*8975f5c5SAndroid Build Coastguard Worker const uint8_t *pixels,
1038*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat)
1039*8975f5c5SAndroid Build Coastguard Worker {
1040*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1041*8975f5c5SAndroid Build Coastguard Worker
1042*8975f5c5SAndroid Build Coastguard Worker bool mustStage = updateMustBeStaged(gl::LevelIndex(index.getLevelIndex()),
1043*8975f5c5SAndroid Build Coastguard Worker vkFormat.getActualImageFormatID(getRequiredImageAccess()));
1044*8975f5c5SAndroid Build Coastguard Worker
1045*8975f5c5SAndroid Build Coastguard Worker vk::ApplyImageUpdate applyUpdate;
1046*8975f5c5SAndroid Build Coastguard Worker if (mustStage)
1047*8975f5c5SAndroid Build Coastguard Worker {
1048*8975f5c5SAndroid Build Coastguard Worker applyUpdate = vk::ApplyImageUpdate::Defer;
1049*8975f5c5SAndroid Build Coastguard Worker }
1050*8975f5c5SAndroid Build Coastguard Worker else
1051*8975f5c5SAndroid Build Coastguard Worker {
1052*8975f5c5SAndroid Build Coastguard Worker // Cannot defer to unlocked tail call if:
1053*8975f5c5SAndroid Build Coastguard Worker //
1054*8975f5c5SAndroid Build Coastguard Worker // - The generate mipmap hint is set: This is because on return the Texture class would
1055*8975f5c5SAndroid Build Coastguard Worker // attempt to generate mipmaps, which may reallocate the image, or fall back to software
1056*8975f5c5SAndroid Build Coastguard Worker // mipmap generation.
1057*8975f5c5SAndroid Build Coastguard Worker // - The texture is incomplete: This is because unlocked tail call is disabled on draw
1058*8975f5c5SAndroid Build Coastguard Worker // calls, but that is when incomplete textures are created and initialized.
1059*8975f5c5SAndroid Build Coastguard Worker const bool canDeferToUnlockedTailCall =
1060*8975f5c5SAndroid Build Coastguard Worker mState.getGenerateMipmapHint() != GL_TRUE && !mState.isInternalIncompleteTexture();
1061*8975f5c5SAndroid Build Coastguard Worker
1062*8975f5c5SAndroid Build Coastguard Worker // When possible flush out updates immediately.
1063*8975f5c5SAndroid Build Coastguard Worker applyUpdate = canDeferToUnlockedTailCall
1064*8975f5c5SAndroid Build Coastguard Worker ? vk::ApplyImageUpdate::ImmediatelyInUnlockedTailCall
1065*8975f5c5SAndroid Build Coastguard Worker : vk::ApplyImageUpdate::Immediately;
1066*8975f5c5SAndroid Build Coastguard Worker }
1067*8975f5c5SAndroid Build Coastguard Worker bool updateAppliedImmediately = false;
1068*8975f5c5SAndroid Build Coastguard Worker
1069*8975f5c5SAndroid Build Coastguard Worker if (unpackBuffer)
1070*8975f5c5SAndroid Build Coastguard Worker {
1071*8975f5c5SAndroid Build Coastguard Worker BufferVk *unpackBufferVk = vk::GetImpl(unpackBuffer);
1072*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper &bufferHelper = unpackBufferVk->getBuffer();
1073*8975f5c5SAndroid Build Coastguard Worker VkDeviceSize bufferOffset = bufferHelper.getOffset();
1074*8975f5c5SAndroid Build Coastguard Worker uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
1075*8975f5c5SAndroid Build Coastguard Worker GLuint inputRowPitch = 0;
1076*8975f5c5SAndroid Build Coastguard Worker GLuint inputDepthPitch = 0;
1077*8975f5c5SAndroid Build Coastguard Worker GLuint inputSkipBytes = 0;
1078*8975f5c5SAndroid Build Coastguard Worker
1079*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->CalculateBufferInfo(
1080*8975f5c5SAndroid Build Coastguard Worker contextVk, gl::Extents(area.width, area.height, area.depth), formatInfo, unpack, type,
1081*8975f5c5SAndroid Build Coastguard Worker index.usesTex3D(), &inputRowPitch, &inputDepthPitch, &inputSkipBytes));
1082*8975f5c5SAndroid Build Coastguard Worker
1083*8975f5c5SAndroid Build Coastguard Worker size_t offsetBytes = static_cast<size_t>(bufferOffset + offset + inputSkipBytes);
1084*8975f5c5SAndroid Build Coastguard Worker
1085*8975f5c5SAndroid Build Coastguard Worker // Note: cannot directly copy from a depth/stencil PBO. GL requires depth and stencil data
1086*8975f5c5SAndroid Build Coastguard Worker // to be packed, while Vulkan requires them to be separate.
1087*8975f5c5SAndroid Build Coastguard Worker const VkImageAspectFlags aspectFlags =
1088*8975f5c5SAndroid Build Coastguard Worker vk::GetFormatAspectFlags(vkFormat.getIntendedFormat());
1089*8975f5c5SAndroid Build Coastguard Worker const vk::Format &bufferVkFormat =
1090*8975f5c5SAndroid Build Coastguard Worker contextVk->getRenderer()->getFormat(formatInfo.sizedInternalFormat);
1091*8975f5c5SAndroid Build Coastguard Worker
1092*8975f5c5SAndroid Build Coastguard Worker if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()),
1093*8975f5c5SAndroid Build Coastguard Worker vkFormat.getActualImageFormatID(getRequiredImageAccess())) &&
1094*8975f5c5SAndroid Build Coastguard Worker isFastUnpackPossible(vkFormat, offsetBytes, bufferVkFormat))
1095*8975f5c5SAndroid Build Coastguard Worker {
1096*8975f5c5SAndroid Build Coastguard Worker GLuint pixelSize = formatInfo.pixelBytes;
1097*8975f5c5SAndroid Build Coastguard Worker GLuint blockWidth = formatInfo.compressedBlockWidth;
1098*8975f5c5SAndroid Build Coastguard Worker GLuint blockHeight = formatInfo.compressedBlockHeight;
1099*8975f5c5SAndroid Build Coastguard Worker if (!formatInfo.compressed)
1100*8975f5c5SAndroid Build Coastguard Worker {
1101*8975f5c5SAndroid Build Coastguard Worker pixelSize = formatInfo.computePixelBytes(type);
1102*8975f5c5SAndroid Build Coastguard Worker blockWidth = 1;
1103*8975f5c5SAndroid Build Coastguard Worker blockHeight = 1;
1104*8975f5c5SAndroid Build Coastguard Worker }
1105*8975f5c5SAndroid Build Coastguard Worker ASSERT(pixelSize != 0 && inputRowPitch != 0 && blockWidth != 0 && blockHeight != 0);
1106*8975f5c5SAndroid Build Coastguard Worker
1107*8975f5c5SAndroid Build Coastguard Worker GLuint rowLengthPixels = inputRowPitch / pixelSize * blockWidth;
1108*8975f5c5SAndroid Build Coastguard Worker GLuint imageHeightPixels = inputDepthPitch / inputRowPitch * blockHeight;
1109*8975f5c5SAndroid Build Coastguard Worker
1110*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(copyBufferDataToImage(contextVk, &bufferHelper, index, rowLengthPixels,
1111*8975f5c5SAndroid Build Coastguard Worker imageHeightPixels, area, offsetBytes, aspectFlags));
1112*8975f5c5SAndroid Build Coastguard Worker }
1113*8975f5c5SAndroid Build Coastguard Worker else
1114*8975f5c5SAndroid Build Coastguard Worker {
1115*8975f5c5SAndroid Build Coastguard Worker ANGLE_VK_PERF_WARNING(
1116*8975f5c5SAndroid Build Coastguard Worker contextVk, GL_DEBUG_SEVERITY_HIGH,
1117*8975f5c5SAndroid Build Coastguard Worker "TexSubImage with unpack buffer copied on CPU due to store, format "
1118*8975f5c5SAndroid Build Coastguard Worker "or offset restrictions");
1119*8975f5c5SAndroid Build Coastguard Worker
1120*8975f5c5SAndroid Build Coastguard Worker void *mapPtr = nullptr;
1121*8975f5c5SAndroid Build Coastguard Worker
1122*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(unpackBufferVk->mapImpl(contextVk, GL_MAP_READ_BIT, &mapPtr));
1123*8975f5c5SAndroid Build Coastguard Worker
1124*8975f5c5SAndroid Build Coastguard Worker const uint8_t *source =
1125*8975f5c5SAndroid Build Coastguard Worker static_cast<const uint8_t *>(mapPtr) + reinterpret_cast<ptrdiff_t>(pixels);
1126*8975f5c5SAndroid Build Coastguard Worker
1127*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stageSubresourceUpdateImpl(
1128*8975f5c5SAndroid Build Coastguard Worker contextVk, getNativeImageIndex(index),
1129*8975f5c5SAndroid Build Coastguard Worker gl::Extents(area.width, area.height, area.depth),
1130*8975f5c5SAndroid Build Coastguard Worker gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, source, vkFormat,
1131*8975f5c5SAndroid Build Coastguard Worker getRequiredImageAccess(), inputRowPitch, inputDepthPitch, inputSkipBytes,
1132*8975f5c5SAndroid Build Coastguard Worker applyUpdate, &updateAppliedImmediately));
1133*8975f5c5SAndroid Build Coastguard Worker
1134*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(unpackBufferVk->unmapImpl(contextVk));
1135*8975f5c5SAndroid Build Coastguard Worker }
1136*8975f5c5SAndroid Build Coastguard Worker }
1137*8975f5c5SAndroid Build Coastguard Worker else if (pixels)
1138*8975f5c5SAndroid Build Coastguard Worker {
1139*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stageSubresourceUpdate(
1140*8975f5c5SAndroid Build Coastguard Worker contextVk, getNativeImageIndex(index), gl::Extents(area.width, area.height, area.depth),
1141*8975f5c5SAndroid Build Coastguard Worker gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels, vkFormat,
1142*8975f5c5SAndroid Build Coastguard Worker getRequiredImageAccess(), applyUpdate, &updateAppliedImmediately));
1143*8975f5c5SAndroid Build Coastguard Worker }
1144*8975f5c5SAndroid Build Coastguard Worker
1145*8975f5c5SAndroid Build Coastguard Worker if (updateAppliedImmediately)
1146*8975f5c5SAndroid Build Coastguard Worker {
1147*8975f5c5SAndroid Build Coastguard Worker // Return if stageSubresourceUpdate already applied the update
1148*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1149*8975f5c5SAndroid Build Coastguard Worker }
1150*8975f5c5SAndroid Build Coastguard Worker
1151*8975f5c5SAndroid Build Coastguard Worker // Flush the staged updates if needed.
1152*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitializedIfUpdatesNeedStageOrFlush(
1153*8975f5c5SAndroid Build Coastguard Worker contextVk, gl::LevelIndex(index.getLevelIndex()), vkFormat, applyUpdate, true));
1154*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1155*8975f5c5SAndroid Build Coastguard Worker }
1156*8975f5c5SAndroid Build Coastguard Worker
copyImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Rectangle & sourceArea,GLenum internalFormat,gl::Framebuffer * source)1157*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyImage(const gl::Context *context,
1158*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1159*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceArea,
1160*8975f5c5SAndroid Build Coastguard Worker GLenum internalFormat,
1161*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *source)
1162*8975f5c5SAndroid Build Coastguard Worker {
1163*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1164*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
1165*8975f5c5SAndroid Build Coastguard Worker
1166*8975f5c5SAndroid Build Coastguard Worker gl::Extents newImageSize(sourceArea.width, sourceArea.height, 1);
1167*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &internalFormatInfo =
1168*8975f5c5SAndroid Build Coastguard Worker gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
1169*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat = renderer->getFormat(internalFormatInfo.sizedInternalFormat);
1170*8975f5c5SAndroid Build Coastguard Worker
1171*8975f5c5SAndroid Build Coastguard Worker // Fall back to renderable format if copy cannot be done in transfer. Must be done before
1172*8975f5c5SAndroid Build Coastguard Worker // the dst format is accessed anywhere (in |redefineLevel| and |copySubImageImpl|).
1173*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderableIfCopyTexImageCannotTransfer(contextVk, internalFormatInfo, source));
1174*8975f5c5SAndroid Build Coastguard Worker
1175*8975f5c5SAndroid Build Coastguard Worker // The texture level being redefined might be the same as the one bound to the framebuffer.
1176*8975f5c5SAndroid Build Coastguard Worker // This _could_ be supported by using a temp image before redefining the level (and potentially
1177*8975f5c5SAndroid Build Coastguard Worker // discarding the image). However, this is currently unimplemented.
1178*8975f5c5SAndroid Build Coastguard Worker FramebufferVk *framebufferVk = vk::GetImpl(source);
1179*8975f5c5SAndroid Build Coastguard Worker RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
1180*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *srcImage = &colorReadRT->getImageForCopy();
1181*8975f5c5SAndroid Build Coastguard Worker const bool isCubeMap = index.getType() == gl::TextureType::CubeMap;
1182*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex levelIndex(getNativeImageIndex(index).getLevelIndex());
1183*8975f5c5SAndroid Build Coastguard Worker const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
1184*8975f5c5SAndroid Build Coastguard Worker const uint32_t redefinedFace = isCubeMap ? layerIndex : 0;
1185*8975f5c5SAndroid Build Coastguard Worker const uint32_t sourceFace = isCubeMap ? colorReadRT->getLayerIndex() : 0;
1186*8975f5c5SAndroid Build Coastguard Worker const bool isSelfCopy = mImage == srcImage && levelIndex == colorReadRT->getLevelIndex() &&
1187*8975f5c5SAndroid Build Coastguard Worker redefinedFace == sourceFace;
1188*8975f5c5SAndroid Build Coastguard Worker
1189*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(redefineLevel(context, index, vkFormat, newImageSize));
1190*8975f5c5SAndroid Build Coastguard Worker
1191*8975f5c5SAndroid Build Coastguard Worker if (isSelfCopy)
1192*8975f5c5SAndroid Build Coastguard Worker {
1193*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
1194*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1195*8975f5c5SAndroid Build Coastguard Worker }
1196*8975f5c5SAndroid Build Coastguard Worker
1197*8975f5c5SAndroid Build Coastguard Worker return copySubImageImpl(context, index, gl::Offset(0, 0, 0), sourceArea, internalFormatInfo,
1198*8975f5c5SAndroid Build Coastguard Worker source);
1199*8975f5c5SAndroid Build Coastguard Worker }
1200*8975f5c5SAndroid Build Coastguard Worker
copySubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Offset & destOffset,const gl::Rectangle & sourceArea,gl::Framebuffer * source)1201*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubImage(const gl::Context *context,
1202*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1203*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &destOffset,
1204*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceArea,
1205*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *source)
1206*8975f5c5SAndroid Build Coastguard Worker {
1207*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat ¤tFormat = *mState.getImageDesc(index).format.info;
1208*8975f5c5SAndroid Build Coastguard Worker
1209*8975f5c5SAndroid Build Coastguard Worker // Fall back to renderable format if copy cannot be done in transfer. Must be done before
1210*8975f5c5SAndroid Build Coastguard Worker // the dst format is accessed anywhere (in |redefineLevel| and |copySubImageImpl|).
1211*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
1212*8975f5c5SAndroid Build Coastguard Worker ensureRenderableIfCopyTexImageCannotTransfer(vk::GetImpl(context), currentFormat, source));
1213*8975f5c5SAndroid Build Coastguard Worker
1214*8975f5c5SAndroid Build Coastguard Worker return copySubImageImpl(context, index, destOffset, sourceArea, currentFormat, source);
1215*8975f5c5SAndroid Build Coastguard Worker }
1216*8975f5c5SAndroid Build Coastguard Worker
copyTexture(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,GLenum type,GLint sourceLevelGL,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,const gl::Texture * source)1217*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyTexture(const gl::Context *context,
1218*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1219*8975f5c5SAndroid Build Coastguard Worker GLenum internalFormat,
1220*8975f5c5SAndroid Build Coastguard Worker GLenum type,
1221*8975f5c5SAndroid Build Coastguard Worker GLint sourceLevelGL,
1222*8975f5c5SAndroid Build Coastguard Worker bool unpackFlipY,
1223*8975f5c5SAndroid Build Coastguard Worker bool unpackPremultiplyAlpha,
1224*8975f5c5SAndroid Build Coastguard Worker bool unpackUnmultiplyAlpha,
1225*8975f5c5SAndroid Build Coastguard Worker const gl::Texture *source)
1226*8975f5c5SAndroid Build Coastguard Worker {
1227*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1228*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
1229*8975f5c5SAndroid Build Coastguard Worker
1230*8975f5c5SAndroid Build Coastguard Worker TextureVk *sourceVk = vk::GetImpl(source);
1231*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &srcImageDesc =
1232*8975f5c5SAndroid Build Coastguard Worker sourceVk->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevelGL);
1233*8975f5c5SAndroid Build Coastguard Worker gl::Box sourceBox(gl::kOffsetZero, srcImageDesc.size);
1234*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &dstFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
1235*8975f5c5SAndroid Build Coastguard Worker const vk::Format &dstVkFormat = renderer->getFormat(dstFormatInfo.sizedInternalFormat);
1236*8975f5c5SAndroid Build Coastguard Worker
1237*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1238*8975f5c5SAndroid Build Coastguard Worker
1239*8975f5c5SAndroid Build Coastguard Worker // Fall back to renderable format if copy cannot be done in transfer. Must be done before
1240*8975f5c5SAndroid Build Coastguard Worker // the dst format is accessed anywhere (in |redefineLevel| and |copySubTextureImpl|).
1241*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderableIfCopyTextureCannotTransfer(contextVk, dstFormatInfo, unpackFlipY,
1242*8975f5c5SAndroid Build Coastguard Worker unpackPremultiplyAlpha,
1243*8975f5c5SAndroid Build Coastguard Worker unpackUnmultiplyAlpha, sourceVk));
1244*8975f5c5SAndroid Build Coastguard Worker
1245*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(redefineLevel(context, index, dstVkFormat, srcImageDesc.size));
1246*8975f5c5SAndroid Build Coastguard Worker
1247*8975f5c5SAndroid Build Coastguard Worker return copySubTextureImpl(contextVk, index, gl::kOffsetZero, dstFormatInfo,
1248*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex(sourceLevelGL), sourceBox, unpackFlipY,
1249*8975f5c5SAndroid Build Coastguard Worker unpackPremultiplyAlpha, unpackUnmultiplyAlpha, sourceVk);
1250*8975f5c5SAndroid Build Coastguard Worker }
1251*8975f5c5SAndroid Build Coastguard Worker
copySubTexture(const gl::Context * context,const gl::ImageIndex & index,const gl::Offset & dstOffset,GLint srcLevelGL,const gl::Box & sourceBox,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,const gl::Texture * source)1252*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubTexture(const gl::Context *context,
1253*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1254*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &dstOffset,
1255*8975f5c5SAndroid Build Coastguard Worker GLint srcLevelGL,
1256*8975f5c5SAndroid Build Coastguard Worker const gl::Box &sourceBox,
1257*8975f5c5SAndroid Build Coastguard Worker bool unpackFlipY,
1258*8975f5c5SAndroid Build Coastguard Worker bool unpackPremultiplyAlpha,
1259*8975f5c5SAndroid Build Coastguard Worker bool unpackUnmultiplyAlpha,
1260*8975f5c5SAndroid Build Coastguard Worker const gl::Texture *source)
1261*8975f5c5SAndroid Build Coastguard Worker {
1262*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1263*8975f5c5SAndroid Build Coastguard Worker
1264*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget target = index.getTarget();
1265*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex dstLevelGL(index.getLevelIndex());
1266*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &dstFormatInfo =
1267*8975f5c5SAndroid Build Coastguard Worker *mState.getImageDesc(target, dstLevelGL.get()).format.info;
1268*8975f5c5SAndroid Build Coastguard Worker
1269*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
1270*8975f5c5SAndroid Build Coastguard Worker vk::GetImpl(source)->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1271*8975f5c5SAndroid Build Coastguard Worker
1272*8975f5c5SAndroid Build Coastguard Worker // Fall back to renderable format if copy cannot be done in transfer. Must be done before
1273*8975f5c5SAndroid Build Coastguard Worker // the dst format is accessed anywhere (in |copySubTextureImpl|).
1274*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderableIfCopyTextureCannotTransfer(
1275*8975f5c5SAndroid Build Coastguard Worker contextVk, dstFormatInfo, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
1276*8975f5c5SAndroid Build Coastguard Worker vk::GetImpl(source)));
1277*8975f5c5SAndroid Build Coastguard Worker
1278*8975f5c5SAndroid Build Coastguard Worker return copySubTextureImpl(contextVk, index, dstOffset, dstFormatInfo,
1279*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex(srcLevelGL), sourceBox, unpackFlipY,
1280*8975f5c5SAndroid Build Coastguard Worker unpackPremultiplyAlpha, unpackUnmultiplyAlpha, vk::GetImpl(source));
1281*8975f5c5SAndroid Build Coastguard Worker }
1282*8975f5c5SAndroid Build Coastguard Worker
copyRenderbufferSubData(const gl::Context * context,const gl::Renderbuffer * srcBuffer,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)1283*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyRenderbufferSubData(const gl::Context *context,
1284*8975f5c5SAndroid Build Coastguard Worker const gl::Renderbuffer *srcBuffer,
1285*8975f5c5SAndroid Build Coastguard Worker GLint srcLevel,
1286*8975f5c5SAndroid Build Coastguard Worker GLint srcX,
1287*8975f5c5SAndroid Build Coastguard Worker GLint srcY,
1288*8975f5c5SAndroid Build Coastguard Worker GLint srcZ,
1289*8975f5c5SAndroid Build Coastguard Worker GLint dstLevel,
1290*8975f5c5SAndroid Build Coastguard Worker GLint dstX,
1291*8975f5c5SAndroid Build Coastguard Worker GLint dstY,
1292*8975f5c5SAndroid Build Coastguard Worker GLint dstZ,
1293*8975f5c5SAndroid Build Coastguard Worker GLsizei srcWidth,
1294*8975f5c5SAndroid Build Coastguard Worker GLsizei srcHeight,
1295*8975f5c5SAndroid Build Coastguard Worker GLsizei srcDepth)
1296*8975f5c5SAndroid Build Coastguard Worker {
1297*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1298*8975f5c5SAndroid Build Coastguard Worker RenderbufferVk *sourceVk = vk::GetImpl(srcBuffer);
1299*8975f5c5SAndroid Build Coastguard Worker
1300*8975f5c5SAndroid Build Coastguard Worker // Make sure the source/destination targets are initialized and all staged updates are flushed.
1301*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(sourceVk->ensureImageInitialized(context));
1302*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1303*8975f5c5SAndroid Build Coastguard Worker
1304*8975f5c5SAndroid Build Coastguard Worker return vk::ImageHelper::CopyImageSubData(context, sourceVk->getImage(), srcLevel, srcX, srcY,
1305*8975f5c5SAndroid Build Coastguard Worker srcZ, mImage, dstLevel, dstX, dstY, dstZ, srcWidth,
1306*8975f5c5SAndroid Build Coastguard Worker srcHeight, srcDepth);
1307*8975f5c5SAndroid Build Coastguard Worker }
1308*8975f5c5SAndroid Build Coastguard Worker
copyTextureSubData(const gl::Context * context,const gl::Texture * srcTexture,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)1309*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyTextureSubData(const gl::Context *context,
1310*8975f5c5SAndroid Build Coastguard Worker const gl::Texture *srcTexture,
1311*8975f5c5SAndroid Build Coastguard Worker GLint srcLevel,
1312*8975f5c5SAndroid Build Coastguard Worker GLint srcX,
1313*8975f5c5SAndroid Build Coastguard Worker GLint srcY,
1314*8975f5c5SAndroid Build Coastguard Worker GLint srcZ,
1315*8975f5c5SAndroid Build Coastguard Worker GLint dstLevel,
1316*8975f5c5SAndroid Build Coastguard Worker GLint dstX,
1317*8975f5c5SAndroid Build Coastguard Worker GLint dstY,
1318*8975f5c5SAndroid Build Coastguard Worker GLint dstZ,
1319*8975f5c5SAndroid Build Coastguard Worker GLsizei srcWidth,
1320*8975f5c5SAndroid Build Coastguard Worker GLsizei srcHeight,
1321*8975f5c5SAndroid Build Coastguard Worker GLsizei srcDepth)
1322*8975f5c5SAndroid Build Coastguard Worker {
1323*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1324*8975f5c5SAndroid Build Coastguard Worker TextureVk *sourceVk = vk::GetImpl(srcTexture);
1325*8975f5c5SAndroid Build Coastguard Worker
1326*8975f5c5SAndroid Build Coastguard Worker // Make sure the source/destination targets are initialized and all staged updates are flushed.
1327*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1328*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1329*8975f5c5SAndroid Build Coastguard Worker
1330*8975f5c5SAndroid Build Coastguard Worker return vk::ImageHelper::CopyImageSubData(context, &sourceVk->getImage(), srcLevel, srcX, srcY,
1331*8975f5c5SAndroid Build Coastguard Worker srcZ, mImage, dstLevel, dstX, dstY, dstZ, srcWidth,
1332*8975f5c5SAndroid Build Coastguard Worker srcHeight, srcDepth);
1333*8975f5c5SAndroid Build Coastguard Worker }
1334*8975f5c5SAndroid Build Coastguard Worker
copyCompressedTexture(const gl::Context * context,const gl::Texture * source)1335*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyCompressedTexture(const gl::Context *context,
1336*8975f5c5SAndroid Build Coastguard Worker const gl::Texture *source)
1337*8975f5c5SAndroid Build Coastguard Worker {
1338*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1339*8975f5c5SAndroid Build Coastguard Worker TextureVk *sourceVk = vk::GetImpl(source);
1340*8975f5c5SAndroid Build Coastguard Worker
1341*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());
1342*8975f5c5SAndroid Build Coastguard Worker constexpr GLint sourceLevelGL = 0;
1343*8975f5c5SAndroid Build Coastguard Worker constexpr GLint destLevelGL = 0;
1344*8975f5c5SAndroid Build Coastguard Worker
1345*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &internalFormat = *source->getFormat(sourceTarget, sourceLevelGL).info;
1346*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat =
1347*8975f5c5SAndroid Build Coastguard Worker contextVk->getRenderer()->getFormat(internalFormat.sizedInternalFormat);
1348*8975f5c5SAndroid Build Coastguard Worker const gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevelGL)),
1349*8975f5c5SAndroid Build Coastguard Worker static_cast<int>(source->getHeight(sourceTarget, sourceLevelGL)),
1350*8975f5c5SAndroid Build Coastguard Worker static_cast<int>(source->getDepth(sourceTarget, sourceLevelGL)));
1351*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(sourceTarget, destLevelGL, 1);
1352*8975f5c5SAndroid Build Coastguard Worker
1353*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(redefineLevel(context, destIndex, vkFormat, size));
1354*8975f5c5SAndroid Build Coastguard Worker
1355*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1356*8975f5c5SAndroid Build Coastguard Worker
1357*8975f5c5SAndroid Build Coastguard Worker return copySubImageImplWithTransfer(contextVk, destIndex, gl::kOffsetZero, vkFormat,
1358*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex(sourceLevelGL), 0,
1359*8975f5c5SAndroid Build Coastguard Worker gl::Box(gl::kOffsetZero, size), &sourceVk->getImage());
1360*8975f5c5SAndroid Build Coastguard Worker }
1361*8975f5c5SAndroid Build Coastguard Worker
copySubImageImpl(const gl::Context * context,const gl::ImageIndex & index,const gl::Offset & destOffset,const gl::Rectangle & sourceArea,const gl::InternalFormat & internalFormat,gl::Framebuffer * source)1362*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
1363*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1364*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &destOffset,
1365*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceArea,
1366*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &internalFormat,
1367*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *source)
1368*8975f5c5SAndroid Build Coastguard Worker {
1369*8975f5c5SAndroid Build Coastguard Worker gl::Extents fbSize = source->getReadColorAttachment()->getSize();
1370*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle clippedSourceArea;
1371*8975f5c5SAndroid Build Coastguard Worker if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
1372*8975f5c5SAndroid Build Coastguard Worker &clippedSourceArea))
1373*8975f5c5SAndroid Build Coastguard Worker {
1374*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1375*8975f5c5SAndroid Build Coastguard Worker }
1376*8975f5c5SAndroid Build Coastguard Worker
1377*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1378*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
1379*8975f5c5SAndroid Build Coastguard Worker FramebufferVk *framebufferVk = vk::GetImpl(source);
1380*8975f5c5SAndroid Build Coastguard Worker
1381*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);
1382*8975f5c5SAndroid Build Coastguard Worker
1383*8975f5c5SAndroid Build Coastguard Worker // If negative offsets are given, clippedSourceArea ensures we don't read from those offsets.
1384*8975f5c5SAndroid Build Coastguard Worker // However, that changes the sourceOffset->destOffset mapping. Here, destOffset is shifted by
1385*8975f5c5SAndroid Build Coastguard Worker // the same amount as clipped to correct the error.
1386*8975f5c5SAndroid Build Coastguard Worker VkImageType imageType = gl_vk::GetImageType(mState.getType());
1387*8975f5c5SAndroid Build Coastguard Worker int zOffset = (imageType == VK_IMAGE_TYPE_3D) ? destOffset.z : 0;
1388*8975f5c5SAndroid Build Coastguard Worker const gl::Offset modifiedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
1389*8975f5c5SAndroid Build Coastguard Worker destOffset.y + clippedSourceArea.y - sourceArea.y, zOffset);
1390*8975f5c5SAndroid Build Coastguard Worker
1391*8975f5c5SAndroid Build Coastguard Worker RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
1392*8975f5c5SAndroid Build Coastguard Worker
1393*8975f5c5SAndroid Build Coastguard Worker angle::FormatID srcIntendedFormatID = colorReadRT->getImageIntendedFormatID();
1394*8975f5c5SAndroid Build Coastguard Worker angle::FormatID srcActualFormatID = colorReadRT->getImageActualFormatID();
1395*8975f5c5SAndroid Build Coastguard Worker VkImageTiling srcTilingMode = colorReadRT->getImageForCopy().getTilingMode();
1396*8975f5c5SAndroid Build Coastguard Worker const vk::Format &dstFormat = renderer->getFormat(internalFormat.sizedInternalFormat);
1397*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstIntendedFormatID = dstFormat.getIntendedFormatID();
1398*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstActualFormatID = dstFormat.getActualImageFormatID(getRequiredImageAccess());
1399*8975f5c5SAndroid Build Coastguard Worker VkImageTiling destTilingMode = getTilingMode();
1400*8975f5c5SAndroid Build Coastguard Worker
1401*8975f5c5SAndroid Build Coastguard Worker bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO();
1402*8975f5c5SAndroid Build Coastguard Worker
1403*8975f5c5SAndroid Build Coastguard Worker gl::Box clippedSourceBox(clippedSourceArea.x, clippedSourceArea.y, colorReadRT->getLayerIndex(),
1404*8975f5c5SAndroid Build Coastguard Worker clippedSourceArea.width, clippedSourceArea.height, 1);
1405*8975f5c5SAndroid Build Coastguard Worker
1406*8975f5c5SAndroid Build Coastguard Worker // If it's possible to perform the copy with a transfer, that's the best option.
1407*8975f5c5SAndroid Build Coastguard Worker if (CanCopyWithTransferForTexImage(renderer, srcIntendedFormatID, srcActualFormatID,
1408*8975f5c5SAndroid Build Coastguard Worker srcTilingMode, dstIntendedFormatID, dstActualFormatID,
1409*8975f5c5SAndroid Build Coastguard Worker destTilingMode, isViewportFlipY))
1410*8975f5c5SAndroid Build Coastguard Worker {
1411*8975f5c5SAndroid Build Coastguard Worker return copySubImageImplWithTransfer(contextVk, offsetImageIndex, modifiedDestOffset,
1412*8975f5c5SAndroid Build Coastguard Worker dstFormat, colorReadRT->getLevelIndex(),
1413*8975f5c5SAndroid Build Coastguard Worker colorReadRT->getLayerIndex(), clippedSourceBox,
1414*8975f5c5SAndroid Build Coastguard Worker &colorReadRT->getImageForCopy());
1415*8975f5c5SAndroid Build Coastguard Worker }
1416*8975f5c5SAndroid Build Coastguard Worker
1417*8975f5c5SAndroid Build Coastguard Worker // If it's possible to perform the copy with a draw call, do that.
1418*8975f5c5SAndroid Build Coastguard Worker if (CanCopyWithDraw(renderer, srcActualFormatID, srcTilingMode, dstActualFormatID,
1419*8975f5c5SAndroid Build Coastguard Worker destTilingMode))
1420*8975f5c5SAndroid Build Coastguard Worker {
1421*8975f5c5SAndroid Build Coastguard Worker // Layer count can only be 1 as the source is a framebuffer.
1422*8975f5c5SAndroid Build Coastguard Worker ASSERT(offsetImageIndex.getLayerCount() == 1);
1423*8975f5c5SAndroid Build Coastguard Worker
1424*8975f5c5SAndroid Build Coastguard Worker // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
1425*8975f5c5SAndroid Build Coastguard Worker // Otherwise the view serials would not reflect the render pass they are really used in.
1426*8975f5c5SAndroid Build Coastguard Worker // http://crbug.com/1272266#c22
1427*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
1428*8975f5c5SAndroid Build Coastguard Worker contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));
1429*8975f5c5SAndroid Build Coastguard Worker
1430*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView *copyImageView = nullptr;
1431*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(colorReadRT->getCopyImageView(contextVk, ©ImageView));
1432*8975f5c5SAndroid Build Coastguard Worker
1433*8975f5c5SAndroid Build Coastguard Worker return copySubImageImplWithDraw(contextVk, offsetImageIndex, modifiedDestOffset, dstFormat,
1434*8975f5c5SAndroid Build Coastguard Worker colorReadRT->getLevelIndex(), clippedSourceBox,
1435*8975f5c5SAndroid Build Coastguard Worker isViewportFlipY, false, false, false,
1436*8975f5c5SAndroid Build Coastguard Worker &colorReadRT->getImageForCopy(), copyImageView,
1437*8975f5c5SAndroid Build Coastguard Worker contextVk->getRotationReadFramebuffer());
1438*8975f5c5SAndroid Build Coastguard Worker }
1439*8975f5c5SAndroid Build Coastguard Worker
1440*8975f5c5SAndroid Build Coastguard Worker ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
1441*8975f5c5SAndroid Build Coastguard Worker "Texture copied on CPU due to format restrictions");
1442*8975f5c5SAndroid Build Coastguard Worker
1443*8975f5c5SAndroid Build Coastguard Worker // Do a CPU readback that does the conversion, and then stage the change to the pixel buffer.
1444*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stageSubresourceUpdateFromFramebuffer(
1445*8975f5c5SAndroid Build Coastguard Worker context, offsetImageIndex, clippedSourceArea, modifiedDestOffset,
1446*8975f5c5SAndroid Build Coastguard Worker gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat,
1447*8975f5c5SAndroid Build Coastguard Worker getRequiredImageAccess(), framebufferVk));
1448*8975f5c5SAndroid Build Coastguard Worker
1449*8975f5c5SAndroid Build Coastguard Worker // Flush out staged update if possible
1450*8975f5c5SAndroid Build Coastguard Worker if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), dstActualFormatID))
1451*8975f5c5SAndroid Build Coastguard Worker {
1452*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(flushImageStagedUpdates(contextVk));
1453*8975f5c5SAndroid Build Coastguard Worker }
1454*8975f5c5SAndroid Build Coastguard Worker
1455*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1456*8975f5c5SAndroid Build Coastguard Worker }
1457*8975f5c5SAndroid Build Coastguard Worker
copySubTextureImpl(ContextVk * contextVk,const gl::ImageIndex & index,const gl::Offset & dstOffset,const gl::InternalFormat & dstFormat,gl::LevelIndex sourceLevelGL,const gl::Box & sourceBox,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,TextureVk * source)1458*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
1459*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1460*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &dstOffset,
1461*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &dstFormat,
1462*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex sourceLevelGL,
1463*8975f5c5SAndroid Build Coastguard Worker const gl::Box &sourceBox,
1464*8975f5c5SAndroid Build Coastguard Worker bool unpackFlipY,
1465*8975f5c5SAndroid Build Coastguard Worker bool unpackPremultiplyAlpha,
1466*8975f5c5SAndroid Build Coastguard Worker bool unpackUnmultiplyAlpha,
1467*8975f5c5SAndroid Build Coastguard Worker TextureVk *source)
1468*8975f5c5SAndroid Build Coastguard Worker {
1469*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
1470*8975f5c5SAndroid Build Coastguard Worker
1471*8975f5c5SAndroid Build Coastguard Worker const angle::Format &srcIntendedFormat = source->getImage().getIntendedFormat();
1472*8975f5c5SAndroid Build Coastguard Worker angle::FormatID srcFormatID = source->getImage().getActualFormatID();
1473*8975f5c5SAndroid Build Coastguard Worker VkImageTiling srcTilingMode = source->getImage().getTilingMode();
1474*8975f5c5SAndroid Build Coastguard Worker const vk::Format &dstVkFormat = renderer->getFormat(dstFormat.sizedInternalFormat);
1475*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstFormatID = dstVkFormat.getActualImageFormatID(getRequiredImageAccess());
1476*8975f5c5SAndroid Build Coastguard Worker VkImageTiling dstTilingMode = getTilingMode();
1477*8975f5c5SAndroid Build Coastguard Worker
1478*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);
1479*8975f5c5SAndroid Build Coastguard Worker
1480*8975f5c5SAndroid Build Coastguard Worker // If it's possible to perform the copy with a transfer, that's the best option.
1481*8975f5c5SAndroid Build Coastguard Worker if (CanCopyWithTransferForCopyTexture(
1482*8975f5c5SAndroid Build Coastguard Worker renderer, source->getImage(), srcTilingMode, dstVkFormat.getIntendedFormatID(),
1483*8975f5c5SAndroid Build Coastguard Worker dstFormatID, dstTilingMode, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
1484*8975f5c5SAndroid Build Coastguard Worker {
1485*8975f5c5SAndroid Build Coastguard Worker return copySubImageImplWithTransfer(contextVk, offsetImageIndex, dstOffset, dstVkFormat,
1486*8975f5c5SAndroid Build Coastguard Worker sourceLevelGL, sourceBox.z, sourceBox,
1487*8975f5c5SAndroid Build Coastguard Worker &source->getImage());
1488*8975f5c5SAndroid Build Coastguard Worker }
1489*8975f5c5SAndroid Build Coastguard Worker
1490*8975f5c5SAndroid Build Coastguard Worker // If it's possible to perform the copy with a draw call, do that.
1491*8975f5c5SAndroid Build Coastguard Worker if (CanCopyWithDraw(renderer, srcFormatID, srcTilingMode, dstFormatID, dstTilingMode))
1492*8975f5c5SAndroid Build Coastguard Worker {
1493*8975f5c5SAndroid Build Coastguard Worker // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
1494*8975f5c5SAndroid Build Coastguard Worker // Otherwise the view serials would not reflect the render pass they are really used in.
1495*8975f5c5SAndroid Build Coastguard Worker // http://crbug.com/1272266#c22
1496*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
1497*8975f5c5SAndroid Build Coastguard Worker contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));
1498*8975f5c5SAndroid Build Coastguard Worker
1499*8975f5c5SAndroid Build Coastguard Worker return copySubImageImplWithDraw(
1500*8975f5c5SAndroid Build Coastguard Worker contextVk, offsetImageIndex, dstOffset, dstVkFormat, sourceLevelGL, sourceBox, false,
1501*8975f5c5SAndroid Build Coastguard Worker unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha, &source->getImage(),
1502*8975f5c5SAndroid Build Coastguard Worker &source->getCopyImageView(), SurfaceRotation::Identity);
1503*8975f5c5SAndroid Build Coastguard Worker }
1504*8975f5c5SAndroid Build Coastguard Worker
1505*8975f5c5SAndroid Build Coastguard Worker ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
1506*8975f5c5SAndroid Build Coastguard Worker "Texture copied on CPU due to format restrictions");
1507*8975f5c5SAndroid Build Coastguard Worker
1508*8975f5c5SAndroid Build Coastguard Worker // Read back the requested region of the source texture
1509*8975f5c5SAndroid Build Coastguard Worker vk::RendererScoped<vk::BufferHelper> bufferHelper(renderer);
1510*8975f5c5SAndroid Build Coastguard Worker uint8_t *sourceData = nullptr;
1511*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->copyImageDataToBufferAndGetData(
1512*8975f5c5SAndroid Build Coastguard Worker contextVk, sourceLevelGL, sourceBox.depth, sourceBox,
1513*8975f5c5SAndroid Build Coastguard Worker RenderPassClosureReason::CopyTextureOnCPU, &bufferHelper.get(), &sourceData));
1514*8975f5c5SAndroid Build Coastguard Worker
1515*8975f5c5SAndroid Build Coastguard Worker const angle::Format &srcTextureFormat = source->getImage().getActualFormat();
1516*8975f5c5SAndroid Build Coastguard Worker const angle::Format &dstTextureFormat =
1517*8975f5c5SAndroid Build Coastguard Worker dstVkFormat.getActualImageFormat(getRequiredImageAccess());
1518*8975f5c5SAndroid Build Coastguard Worker size_t destinationAllocationSize =
1519*8975f5c5SAndroid Build Coastguard Worker sourceBox.width * sourceBox.height * sourceBox.depth * dstTextureFormat.pixelBytes;
1520*8975f5c5SAndroid Build Coastguard Worker
1521*8975f5c5SAndroid Build Coastguard Worker // Allocate memory in the destination texture for the copy/conversion
1522*8975f5c5SAndroid Build Coastguard Worker uint32_t stagingBaseLayer =
1523*8975f5c5SAndroid Build Coastguard Worker offsetImageIndex.hasLayer() ? offsetImageIndex.getLayerIndex() : dstOffset.z;
1524*8975f5c5SAndroid Build Coastguard Worker uint32_t stagingLayerCount = sourceBox.depth;
1525*8975f5c5SAndroid Build Coastguard Worker gl::Offset stagingOffset = dstOffset;
1526*8975f5c5SAndroid Build Coastguard Worker gl::Extents stagingExtents(sourceBox.width, sourceBox.height, sourceBox.depth);
1527*8975f5c5SAndroid Build Coastguard Worker bool is3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;
1528*8975f5c5SAndroid Build Coastguard Worker
1529*8975f5c5SAndroid Build Coastguard Worker if (is3D)
1530*8975f5c5SAndroid Build Coastguard Worker {
1531*8975f5c5SAndroid Build Coastguard Worker stagingBaseLayer = 0;
1532*8975f5c5SAndroid Build Coastguard Worker stagingLayerCount = 1;
1533*8975f5c5SAndroid Build Coastguard Worker }
1534*8975f5c5SAndroid Build Coastguard Worker else
1535*8975f5c5SAndroid Build Coastguard Worker {
1536*8975f5c5SAndroid Build Coastguard Worker stagingOffset.z = 0;
1537*8975f5c5SAndroid Build Coastguard Worker stagingExtents.depth = 1;
1538*8975f5c5SAndroid Build Coastguard Worker }
1539*8975f5c5SAndroid Build Coastguard Worker
1540*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex stagingIndex = gl::ImageIndex::Make2DArrayRange(
1541*8975f5c5SAndroid Build Coastguard Worker offsetImageIndex.getLevelIndex(), stagingBaseLayer, stagingLayerCount);
1542*8975f5c5SAndroid Build Coastguard Worker
1543*8975f5c5SAndroid Build Coastguard Worker uint8_t *destData = nullptr;
1544*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(contextVk, destinationAllocationSize,
1545*8975f5c5SAndroid Build Coastguard Worker stagingIndex, stagingExtents, stagingOffset,
1546*8975f5c5SAndroid Build Coastguard Worker &destData, dstFormatID));
1547*8975f5c5SAndroid Build Coastguard Worker
1548*8975f5c5SAndroid Build Coastguard Worker // Source and dst data is tightly packed
1549*8975f5c5SAndroid Build Coastguard Worker GLuint srcDataRowPitch = sourceBox.width * srcTextureFormat.pixelBytes;
1550*8975f5c5SAndroid Build Coastguard Worker GLuint dstDataRowPitch = sourceBox.width * dstTextureFormat.pixelBytes;
1551*8975f5c5SAndroid Build Coastguard Worker
1552*8975f5c5SAndroid Build Coastguard Worker GLuint srcDataDepthPitch = srcDataRowPitch * sourceBox.height;
1553*8975f5c5SAndroid Build Coastguard Worker GLuint dstDataDepthPitch = dstDataRowPitch * sourceBox.height;
1554*8975f5c5SAndroid Build Coastguard Worker
1555*8975f5c5SAndroid Build Coastguard Worker rx::PixelReadFunction pixelReadFunction = srcTextureFormat.pixelReadFunction;
1556*8975f5c5SAndroid Build Coastguard Worker rx::PixelWriteFunction pixelWriteFunction = dstTextureFormat.pixelWriteFunction;
1557*8975f5c5SAndroid Build Coastguard Worker
1558*8975f5c5SAndroid Build Coastguard Worker // Fix up the read/write functions for the sake of luminance/alpha that are emulated with
1559*8975f5c5SAndroid Build Coastguard Worker // formats whose channels don't correspond to the original format (alpha is emulated with red,
1560*8975f5c5SAndroid Build Coastguard Worker // and luminance/alpha is emulated with red/green).
1561*8975f5c5SAndroid Build Coastguard Worker if (srcIntendedFormat.isLUMA())
1562*8975f5c5SAndroid Build Coastguard Worker {
1563*8975f5c5SAndroid Build Coastguard Worker pixelReadFunction = srcIntendedFormat.pixelReadFunction;
1564*8975f5c5SAndroid Build Coastguard Worker }
1565*8975f5c5SAndroid Build Coastguard Worker if (dstVkFormat.getIntendedFormat().isLUMA())
1566*8975f5c5SAndroid Build Coastguard Worker {
1567*8975f5c5SAndroid Build Coastguard Worker pixelWriteFunction = dstVkFormat.getIntendedFormat().pixelWriteFunction;
1568*8975f5c5SAndroid Build Coastguard Worker }
1569*8975f5c5SAndroid Build Coastguard Worker
1570*8975f5c5SAndroid Build Coastguard Worker CopyImageCHROMIUM(sourceData, srcDataRowPitch, srcTextureFormat.pixelBytes, srcDataDepthPitch,
1571*8975f5c5SAndroid Build Coastguard Worker pixelReadFunction, destData, dstDataRowPitch, dstTextureFormat.pixelBytes,
1572*8975f5c5SAndroid Build Coastguard Worker dstDataDepthPitch, pixelWriteFunction, dstFormat.format,
1573*8975f5c5SAndroid Build Coastguard Worker dstFormat.componentType, sourceBox.width, sourceBox.height, sourceBox.depth,
1574*8975f5c5SAndroid Build Coastguard Worker unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
1575*8975f5c5SAndroid Build Coastguard Worker
1576*8975f5c5SAndroid Build Coastguard Worker if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), dstFormatID))
1577*8975f5c5SAndroid Build Coastguard Worker {
1578*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(flushImageStagedUpdates(contextVk));
1579*8975f5c5SAndroid Build Coastguard Worker }
1580*8975f5c5SAndroid Build Coastguard Worker
1581*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1582*8975f5c5SAndroid Build Coastguard Worker }
1583*8975f5c5SAndroid Build Coastguard Worker
copySubImageImplWithTransfer(ContextVk * contextVk,const gl::ImageIndex & index,const gl::Offset & dstOffset,const vk::Format & dstFormat,gl::LevelIndex sourceLevelGL,size_t sourceLayer,const gl::Box & sourceBox,vk::ImageHelper * srcImage)1584*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
1585*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1586*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &dstOffset,
1587*8975f5c5SAndroid Build Coastguard Worker const vk::Format &dstFormat,
1588*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex sourceLevelGL,
1589*8975f5c5SAndroid Build Coastguard Worker size_t sourceLayer,
1590*8975f5c5SAndroid Build Coastguard Worker const gl::Box &sourceBox,
1591*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *srcImage)
1592*8975f5c5SAndroid Build Coastguard Worker {
1593*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
1594*8975f5c5SAndroid Build Coastguard Worker
1595*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex level(index.getLevelIndex());
1596*8975f5c5SAndroid Build Coastguard Worker uint32_t baseLayer = index.hasLayer() ? index.getLayerIndex() : dstOffset.z;
1597*8975f5c5SAndroid Build Coastguard Worker uint32_t layerCount = sourceBox.depth;
1598*8975f5c5SAndroid Build Coastguard Worker
1599*8975f5c5SAndroid Build Coastguard Worker gl::Offset srcOffset = {sourceBox.x, sourceBox.y, sourceBox.z};
1600*8975f5c5SAndroid Build Coastguard Worker gl::Extents extents = {sourceBox.width, sourceBox.height, sourceBox.depth};
1601*8975f5c5SAndroid Build Coastguard Worker
1602*8975f5c5SAndroid Build Coastguard Worker // Change source layout if necessary
1603*8975f5c5SAndroid Build Coastguard Worker vk::CommandBufferAccess access;
1604*8975f5c5SAndroid Build Coastguard Worker access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
1605*8975f5c5SAndroid Build Coastguard Worker
1606*8975f5c5SAndroid Build Coastguard Worker VkImageSubresourceLayers srcSubresource = {};
1607*8975f5c5SAndroid Build Coastguard Worker srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1608*8975f5c5SAndroid Build Coastguard Worker srcSubresource.mipLevel = srcImage->toVkLevel(sourceLevelGL).get();
1609*8975f5c5SAndroid Build Coastguard Worker srcSubresource.baseArrayLayer = static_cast<uint32_t>(sourceLayer);
1610*8975f5c5SAndroid Build Coastguard Worker srcSubresource.layerCount = layerCount;
1611*8975f5c5SAndroid Build Coastguard Worker
1612*8975f5c5SAndroid Build Coastguard Worker bool isSrc3D = srcImage->getExtents().depth > 1;
1613*8975f5c5SAndroid Build Coastguard Worker bool isDest3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;
1614*8975f5c5SAndroid Build Coastguard Worker
1615*8975f5c5SAndroid Build Coastguard Worker if (isSrc3D)
1616*8975f5c5SAndroid Build Coastguard Worker {
1617*8975f5c5SAndroid Build Coastguard Worker Set3DBaseArrayLayerAndLayerCount(&srcSubresource);
1618*8975f5c5SAndroid Build Coastguard Worker }
1619*8975f5c5SAndroid Build Coastguard Worker else
1620*8975f5c5SAndroid Build Coastguard Worker {
1621*8975f5c5SAndroid Build Coastguard Worker ASSERT(srcSubresource.baseArrayLayer == static_cast<uint32_t>(srcOffset.z));
1622*8975f5c5SAndroid Build Coastguard Worker srcOffset.z = 0;
1623*8975f5c5SAndroid Build Coastguard Worker }
1624*8975f5c5SAndroid Build Coastguard Worker
1625*8975f5c5SAndroid Build Coastguard Worker gl::Offset dstOffsetModified = dstOffset;
1626*8975f5c5SAndroid Build Coastguard Worker if (!isDest3D)
1627*8975f5c5SAndroid Build Coastguard Worker {
1628*8975f5c5SAndroid Build Coastguard Worker // If destination is not 3D, destination offset must be 0.
1629*8975f5c5SAndroid Build Coastguard Worker dstOffsetModified.z = 0;
1630*8975f5c5SAndroid Build Coastguard Worker }
1631*8975f5c5SAndroid Build Coastguard Worker
1632*8975f5c5SAndroid Build Coastguard Worker // Perform self-copies through a staging buffer.
1633*8975f5c5SAndroid Build Coastguard Worker // TODO: optimize to copy directly if possible. http://anglebug.com/42263319
1634*8975f5c5SAndroid Build Coastguard Worker bool isSelfCopy = mImage == srcImage;
1635*8975f5c5SAndroid Build Coastguard Worker
1636*8975f5c5SAndroid Build Coastguard Worker // If destination is valid, copy the source directly into it.
1637*8975f5c5SAndroid Build Coastguard Worker if (shouldUpdateBeFlushed(level, dstFormat.getActualImageFormatID(getRequiredImageAccess())) &&
1638*8975f5c5SAndroid Build Coastguard Worker !isSelfCopy)
1639*8975f5c5SAndroid Build Coastguard Worker {
1640*8975f5c5SAndroid Build Coastguard Worker // Make sure any updates to the image are already flushed.
1641*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1642*8975f5c5SAndroid Build Coastguard Worker
1643*8975f5c5SAndroid Build Coastguard Worker access.onImageTransferWrite(level, 1, baseLayer, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
1644*8975f5c5SAndroid Build Coastguard Worker mImage);
1645*8975f5c5SAndroid Build Coastguard Worker
1646*8975f5c5SAndroid Build Coastguard Worker vk::OutsideRenderPassCommandBuffer *commandBuffer;
1647*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1648*8975f5c5SAndroid Build Coastguard Worker
1649*8975f5c5SAndroid Build Coastguard Worker VkImageSubresourceLayers destSubresource = srcSubresource;
1650*8975f5c5SAndroid Build Coastguard Worker destSubresource.mipLevel = mImage->toVkLevel(level).get();
1651*8975f5c5SAndroid Build Coastguard Worker destSubresource.baseArrayLayer = baseLayer;
1652*8975f5c5SAndroid Build Coastguard Worker destSubresource.layerCount = layerCount;
1653*8975f5c5SAndroid Build Coastguard Worker
1654*8975f5c5SAndroid Build Coastguard Worker if (isDest3D)
1655*8975f5c5SAndroid Build Coastguard Worker {
1656*8975f5c5SAndroid Build Coastguard Worker Set3DBaseArrayLayerAndLayerCount(&destSubresource);
1657*8975f5c5SAndroid Build Coastguard Worker }
1658*8975f5c5SAndroid Build Coastguard Worker else if (!isSrc3D)
1659*8975f5c5SAndroid Build Coastguard Worker {
1660*8975f5c5SAndroid Build Coastguard Worker // extents.depth should be set to layer count if any of the source or destination is a
1661*8975f5c5SAndroid Build Coastguard Worker // 2D Array. If both are 2D Array, it should be set to 1.
1662*8975f5c5SAndroid Build Coastguard Worker extents.depth = 1;
1663*8975f5c5SAndroid Build Coastguard Worker }
1664*8975f5c5SAndroid Build Coastguard Worker
1665*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper::Copy(renderer, srcImage, mImage, srcOffset, dstOffsetModified, extents,
1666*8975f5c5SAndroid Build Coastguard Worker srcSubresource, destSubresource, commandBuffer);
1667*8975f5c5SAndroid Build Coastguard Worker }
1668*8975f5c5SAndroid Build Coastguard Worker else
1669*8975f5c5SAndroid Build Coastguard Worker {
1670*8975f5c5SAndroid Build Coastguard Worker // Create a temporary image to stage the copy
1671*8975f5c5SAndroid Build Coastguard Worker std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
1672*8975f5c5SAndroid Build Coastguard Worker stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();
1673*8975f5c5SAndroid Build Coastguard Worker
1674*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(stagingImage->get().init2DStaging(
1675*8975f5c5SAndroid Build Coastguard Worker contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
1676*8975f5c5SAndroid Build Coastguard Worker gl::Extents(sourceBox.width, sourceBox.height, 1), dstFormat.getIntendedFormatID(),
1677*8975f5c5SAndroid Build Coastguard Worker dstFormat.getActualImageFormatID(getRequiredImageAccess()), kTransferImageFlags,
1678*8975f5c5SAndroid Build Coastguard Worker layerCount));
1679*8975f5c5SAndroid Build Coastguard Worker
1680*8975f5c5SAndroid Build Coastguard Worker access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
1681*8975f5c5SAndroid Build Coastguard Worker &stagingImage->get());
1682*8975f5c5SAndroid Build Coastguard Worker
1683*8975f5c5SAndroid Build Coastguard Worker vk::OutsideRenderPassCommandBuffer *commandBuffer;
1684*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1685*8975f5c5SAndroid Build Coastguard Worker
1686*8975f5c5SAndroid Build Coastguard Worker VkImageSubresourceLayers destSubresource = srcSubresource;
1687*8975f5c5SAndroid Build Coastguard Worker destSubresource.mipLevel = 0;
1688*8975f5c5SAndroid Build Coastguard Worker destSubresource.baseArrayLayer = 0;
1689*8975f5c5SAndroid Build Coastguard Worker destSubresource.layerCount = layerCount;
1690*8975f5c5SAndroid Build Coastguard Worker
1691*8975f5c5SAndroid Build Coastguard Worker if (!isSrc3D)
1692*8975f5c5SAndroid Build Coastguard Worker {
1693*8975f5c5SAndroid Build Coastguard Worker // extents.depth should be set to layer count if any of the source or destination is a
1694*8975f5c5SAndroid Build Coastguard Worker // 2D Array. If both are 2D Array, it should be set to 1.
1695*8975f5c5SAndroid Build Coastguard Worker extents.depth = 1;
1696*8975f5c5SAndroid Build Coastguard Worker }
1697*8975f5c5SAndroid Build Coastguard Worker
1698*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper::Copy(renderer, srcImage, &stagingImage->get(), srcOffset, gl::kOffsetZero,
1699*8975f5c5SAndroid Build Coastguard Worker extents, srcSubresource, destSubresource, commandBuffer);
1700*8975f5c5SAndroid Build Coastguard Worker
1701*8975f5c5SAndroid Build Coastguard Worker // Stage the copy for when the image storage is actually created.
1702*8975f5c5SAndroid Build Coastguard Worker VkImageType imageType = gl_vk::GetImageType(mState.getType());
1703*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex stagingIndex =
1704*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex::Make2DArrayRange(level.get(), baseLayer, layerCount);
1705*8975f5c5SAndroid Build Coastguard Worker mImage->stageSubresourceUpdateFromImage(stagingImage.release(), stagingIndex,
1706*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex(0), dstOffsetModified, extents,
1707*8975f5c5SAndroid Build Coastguard Worker imageType);
1708*8975f5c5SAndroid Build Coastguard Worker }
1709*8975f5c5SAndroid Build Coastguard Worker
1710*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1711*8975f5c5SAndroid Build Coastguard Worker }
1712*8975f5c5SAndroid Build Coastguard Worker
copySubImageImplWithDraw(ContextVk * contextVk,const gl::ImageIndex & index,const gl::Offset & dstOffset,const vk::Format & dstFormat,gl::LevelIndex sourceLevelGL,const gl::Box & sourceBox,bool isSrcFlipY,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,vk::ImageHelper * srcImage,const vk::ImageView * srcView,SurfaceRotation srcFramebufferRotation)1713*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
1714*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
1715*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &dstOffset,
1716*8975f5c5SAndroid Build Coastguard Worker const vk::Format &dstFormat,
1717*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex sourceLevelGL,
1718*8975f5c5SAndroid Build Coastguard Worker const gl::Box &sourceBox,
1719*8975f5c5SAndroid Build Coastguard Worker bool isSrcFlipY,
1720*8975f5c5SAndroid Build Coastguard Worker bool unpackFlipY,
1721*8975f5c5SAndroid Build Coastguard Worker bool unpackPremultiplyAlpha,
1722*8975f5c5SAndroid Build Coastguard Worker bool unpackUnmultiplyAlpha,
1723*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *srcImage,
1724*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView *srcView,
1725*8975f5c5SAndroid Build Coastguard Worker SurfaceRotation srcFramebufferRotation)
1726*8975f5c5SAndroid Build Coastguard Worker {
1727*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
1728*8975f5c5SAndroid Build Coastguard Worker UtilsVk &utilsVk = contextVk->getUtils();
1729*8975f5c5SAndroid Build Coastguard Worker
1730*8975f5c5SAndroid Build Coastguard Worker // Potentially make adjustments for pre-rotation.
1731*8975f5c5SAndroid Build Coastguard Worker gl::Box rotatedSourceBox = sourceBox;
1732*8975f5c5SAndroid Build Coastguard Worker gl::Extents srcExtents = srcImage->getLevelExtents2D(vk::LevelIndex(0));
1733*8975f5c5SAndroid Build Coastguard Worker switch (srcFramebufferRotation)
1734*8975f5c5SAndroid Build Coastguard Worker {
1735*8975f5c5SAndroid Build Coastguard Worker case SurfaceRotation::Identity:
1736*8975f5c5SAndroid Build Coastguard Worker // No adjustments needed
1737*8975f5c5SAndroid Build Coastguard Worker break;
1738*8975f5c5SAndroid Build Coastguard Worker case SurfaceRotation::Rotated90Degrees:
1739*8975f5c5SAndroid Build Coastguard Worker // Turn off y-flip for 90 degrees, as we don't want it affecting the
1740*8975f5c5SAndroid Build Coastguard Worker // shaderParams.srcOffset calculation done in UtilsVk::copyImage().
1741*8975f5c5SAndroid Build Coastguard Worker ASSERT(isSrcFlipY);
1742*8975f5c5SAndroid Build Coastguard Worker isSrcFlipY = false;
1743*8975f5c5SAndroid Build Coastguard Worker std::swap(rotatedSourceBox.x, rotatedSourceBox.y);
1744*8975f5c5SAndroid Build Coastguard Worker std::swap(rotatedSourceBox.width, rotatedSourceBox.height);
1745*8975f5c5SAndroid Build Coastguard Worker std::swap(srcExtents.width, srcExtents.height);
1746*8975f5c5SAndroid Build Coastguard Worker break;
1747*8975f5c5SAndroid Build Coastguard Worker case SurfaceRotation::Rotated180Degrees:
1748*8975f5c5SAndroid Build Coastguard Worker ASSERT(isSrcFlipY);
1749*8975f5c5SAndroid Build Coastguard Worker rotatedSourceBox.x = srcExtents.width - sourceBox.x - sourceBox.width - 1;
1750*8975f5c5SAndroid Build Coastguard Worker rotatedSourceBox.y = srcExtents.height - sourceBox.y - sourceBox.height - 1;
1751*8975f5c5SAndroid Build Coastguard Worker break;
1752*8975f5c5SAndroid Build Coastguard Worker case SurfaceRotation::Rotated270Degrees:
1753*8975f5c5SAndroid Build Coastguard Worker // Turn off y-flip for 270 degrees, as we don't want it affecting the
1754*8975f5c5SAndroid Build Coastguard Worker // shaderParams.srcOffset calculation done in UtilsVk::copyImage(). It is needed
1755*8975f5c5SAndroid Build Coastguard Worker // within the shader (when it will affect how the shader looks-up the source pixel),
1756*8975f5c5SAndroid Build Coastguard Worker // and so shaderParams.flipY is turned on at the right time within
1757*8975f5c5SAndroid Build Coastguard Worker // UtilsVk::copyImage().
1758*8975f5c5SAndroid Build Coastguard Worker ASSERT(isSrcFlipY);
1759*8975f5c5SAndroid Build Coastguard Worker isSrcFlipY = false;
1760*8975f5c5SAndroid Build Coastguard Worker rotatedSourceBox.x = srcExtents.height - sourceBox.y - sourceBox.height - 1;
1761*8975f5c5SAndroid Build Coastguard Worker rotatedSourceBox.y = srcExtents.width - sourceBox.x - sourceBox.width - 1;
1762*8975f5c5SAndroid Build Coastguard Worker std::swap(rotatedSourceBox.width, rotatedSourceBox.height);
1763*8975f5c5SAndroid Build Coastguard Worker std::swap(srcExtents.width, srcExtents.height);
1764*8975f5c5SAndroid Build Coastguard Worker break;
1765*8975f5c5SAndroid Build Coastguard Worker default:
1766*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1767*8975f5c5SAndroid Build Coastguard Worker break;
1768*8975f5c5SAndroid Build Coastguard Worker }
1769*8975f5c5SAndroid Build Coastguard Worker
1770*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex level(index.getLevelIndex());
1771*8975f5c5SAndroid Build Coastguard Worker
1772*8975f5c5SAndroid Build Coastguard Worker UtilsVk::CopyImageParameters params;
1773*8975f5c5SAndroid Build Coastguard Worker params.srcOffset[0] = rotatedSourceBox.x;
1774*8975f5c5SAndroid Build Coastguard Worker params.srcOffset[1] = rotatedSourceBox.y;
1775*8975f5c5SAndroid Build Coastguard Worker params.srcExtents[0] = rotatedSourceBox.width;
1776*8975f5c5SAndroid Build Coastguard Worker params.srcExtents[1] = rotatedSourceBox.height;
1777*8975f5c5SAndroid Build Coastguard Worker params.dstOffset[0] = dstOffset.x;
1778*8975f5c5SAndroid Build Coastguard Worker params.dstOffset[1] = dstOffset.y;
1779*8975f5c5SAndroid Build Coastguard Worker params.srcMip = srcImage->toVkLevel(sourceLevelGL).get();
1780*8975f5c5SAndroid Build Coastguard Worker params.srcSampleCount = srcImage->getSamples();
1781*8975f5c5SAndroid Build Coastguard Worker params.srcHeight = srcExtents.height;
1782*8975f5c5SAndroid Build Coastguard Worker params.dstMip = level;
1783*8975f5c5SAndroid Build Coastguard Worker params.srcPremultiplyAlpha = unpackPremultiplyAlpha && !unpackUnmultiplyAlpha;
1784*8975f5c5SAndroid Build Coastguard Worker params.srcUnmultiplyAlpha = unpackUnmultiplyAlpha && !unpackPremultiplyAlpha;
1785*8975f5c5SAndroid Build Coastguard Worker params.srcFlipY = isSrcFlipY;
1786*8975f5c5SAndroid Build Coastguard Worker params.dstFlipY = unpackFlipY;
1787*8975f5c5SAndroid Build Coastguard Worker params.srcRotation = srcFramebufferRotation;
1788*8975f5c5SAndroid Build Coastguard Worker
1789*8975f5c5SAndroid Build Coastguard Worker uint32_t baseLayer = index.hasLayer() ? index.getLayerIndex() : dstOffset.z;
1790*8975f5c5SAndroid Build Coastguard Worker uint32_t layerCount = sourceBox.depth;
1791*8975f5c5SAndroid Build Coastguard Worker
1792*8975f5c5SAndroid Build Coastguard Worker gl::Extents extents = {sourceBox.width, sourceBox.height, sourceBox.depth};
1793*8975f5c5SAndroid Build Coastguard Worker
1794*8975f5c5SAndroid Build Coastguard Worker bool isSrc3D = srcImage->getExtents().depth > 1;
1795*8975f5c5SAndroid Build Coastguard Worker bool isDest3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;
1796*8975f5c5SAndroid Build Coastguard Worker
1797*8975f5c5SAndroid Build Coastguard Worker // Perform self-copies through a staging buffer.
1798*8975f5c5SAndroid Build Coastguard Worker // TODO: optimize to copy directly if possible. http://anglebug.com/42263319
1799*8975f5c5SAndroid Build Coastguard Worker bool isSelfCopy = mImage == srcImage;
1800*8975f5c5SAndroid Build Coastguard Worker params.srcColorEncoding =
1801*8975f5c5SAndroid Build Coastguard Worker gl::GetSizedInternalFormatInfo(srcImage->getIntendedFormat().glInternalFormat)
1802*8975f5c5SAndroid Build Coastguard Worker .colorEncoding;
1803*8975f5c5SAndroid Build Coastguard Worker params.dstColorEncoding =
1804*8975f5c5SAndroid Build Coastguard Worker gl::GetSizedInternalFormatInfo(dstFormat.getIntendedFormat().glInternalFormat)
1805*8975f5c5SAndroid Build Coastguard Worker .colorEncoding;
1806*8975f5c5SAndroid Build Coastguard Worker
1807*8975f5c5SAndroid Build Coastguard Worker // If destination is valid, copy the source directly into it.
1808*8975f5c5SAndroid Build Coastguard Worker if (shouldUpdateBeFlushed(level, dstFormat.getActualImageFormatID(getRequiredImageAccess())) &&
1809*8975f5c5SAndroid Build Coastguard Worker !isSelfCopy)
1810*8975f5c5SAndroid Build Coastguard Worker {
1811*8975f5c5SAndroid Build Coastguard Worker // Make sure any updates to the image are already flushed.
1812*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(flushImageStagedUpdates(contextVk));
1813*8975f5c5SAndroid Build Coastguard Worker
1814*8975f5c5SAndroid Build Coastguard Worker for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
1815*8975f5c5SAndroid Build Coastguard Worker {
1816*8975f5c5SAndroid Build Coastguard Worker params.srcLayer = layerIndex + sourceBox.z;
1817*8975f5c5SAndroid Build Coastguard Worker params.dstLayer = baseLayer + layerIndex;
1818*8975f5c5SAndroid Build Coastguard Worker
1819*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView *destView;
1820*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getLevelLayerImageView(contextVk, level, baseLayer + layerIndex, &destView));
1821*8975f5c5SAndroid Build Coastguard Worker
1822*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(utilsVk.copyImage(contextVk, mImage, destView, srcImage, srcView, params));
1823*8975f5c5SAndroid Build Coastguard Worker }
1824*8975f5c5SAndroid Build Coastguard Worker }
1825*8975f5c5SAndroid Build Coastguard Worker else
1826*8975f5c5SAndroid Build Coastguard Worker {
1827*8975f5c5SAndroid Build Coastguard Worker GLint samples = srcImage->getSamples();
1828*8975f5c5SAndroid Build Coastguard Worker gl::TextureType stagingTextureType = vk::Get2DTextureType(layerCount, samples);
1829*8975f5c5SAndroid Build Coastguard Worker
1830*8975f5c5SAndroid Build Coastguard Worker // Create a temporary image to stage the copy
1831*8975f5c5SAndroid Build Coastguard Worker std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
1832*8975f5c5SAndroid Build Coastguard Worker stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();
1833*8975f5c5SAndroid Build Coastguard Worker
1834*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(stagingImage->get().init2DStaging(
1835*8975f5c5SAndroid Build Coastguard Worker contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
1836*8975f5c5SAndroid Build Coastguard Worker gl::Extents(sourceBox.width, sourceBox.height, 1), dstFormat.getIntendedFormatID(),
1837*8975f5c5SAndroid Build Coastguard Worker dstFormat.getActualImageFormatID(getRequiredImageAccess()), kDrawStagingImageFlags,
1838*8975f5c5SAndroid Build Coastguard Worker layerCount));
1839*8975f5c5SAndroid Build Coastguard Worker
1840*8975f5c5SAndroid Build Coastguard Worker params.dstOffset[0] = 0;
1841*8975f5c5SAndroid Build Coastguard Worker params.dstOffset[1] = 0;
1842*8975f5c5SAndroid Build Coastguard Worker
1843*8975f5c5SAndroid Build Coastguard Worker for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
1844*8975f5c5SAndroid Build Coastguard Worker {
1845*8975f5c5SAndroid Build Coastguard Worker params.srcLayer = layerIndex + sourceBox.z;
1846*8975f5c5SAndroid Build Coastguard Worker params.dstLayer = layerIndex;
1847*8975f5c5SAndroid Build Coastguard Worker
1848*8975f5c5SAndroid Build Coastguard Worker // Create a temporary view for this layer.
1849*8975f5c5SAndroid Build Coastguard Worker vk::ImageView stagingView;
1850*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(stagingImage->get().initLayerImageView(
1851*8975f5c5SAndroid Build Coastguard Worker contextVk, stagingTextureType, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
1852*8975f5c5SAndroid Build Coastguard Worker &stagingView, vk::LevelIndex(0), 1, layerIndex, 1));
1853*8975f5c5SAndroid Build Coastguard Worker
1854*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(utilsVk.copyImage(contextVk, &stagingImage->get(), &stagingView, srcImage,
1855*8975f5c5SAndroid Build Coastguard Worker srcView, params));
1856*8975f5c5SAndroid Build Coastguard Worker
1857*8975f5c5SAndroid Build Coastguard Worker // Queue the resource for cleanup as soon as the copy above is finished. There's no
1858*8975f5c5SAndroid Build Coastguard Worker // need to keep it around.
1859*8975f5c5SAndroid Build Coastguard Worker contextVk->addGarbage(&stagingView);
1860*8975f5c5SAndroid Build Coastguard Worker }
1861*8975f5c5SAndroid Build Coastguard Worker
1862*8975f5c5SAndroid Build Coastguard Worker if (!isSrc3D)
1863*8975f5c5SAndroid Build Coastguard Worker {
1864*8975f5c5SAndroid Build Coastguard Worker // extents.depth should be set to layer count if any of the source or destination is a
1865*8975f5c5SAndroid Build Coastguard Worker // 2D Array. If both are 2D Array, it should be set to 1.
1866*8975f5c5SAndroid Build Coastguard Worker extents.depth = 1;
1867*8975f5c5SAndroid Build Coastguard Worker }
1868*8975f5c5SAndroid Build Coastguard Worker
1869*8975f5c5SAndroid Build Coastguard Worker gl::Offset dstOffsetModified = dstOffset;
1870*8975f5c5SAndroid Build Coastguard Worker if (!isDest3D)
1871*8975f5c5SAndroid Build Coastguard Worker {
1872*8975f5c5SAndroid Build Coastguard Worker // If destination is not 3D, destination offset must be 0.
1873*8975f5c5SAndroid Build Coastguard Worker dstOffsetModified.z = 0;
1874*8975f5c5SAndroid Build Coastguard Worker }
1875*8975f5c5SAndroid Build Coastguard Worker
1876*8975f5c5SAndroid Build Coastguard Worker // Stage the copy for when the image storage is actually created.
1877*8975f5c5SAndroid Build Coastguard Worker VkImageType imageType = gl_vk::GetImageType(mState.getType());
1878*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex stagingIndex =
1879*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex::Make2DArrayRange(level.get(), baseLayer, layerCount);
1880*8975f5c5SAndroid Build Coastguard Worker mImage->stageSubresourceUpdateFromImage(stagingImage.release(), stagingIndex,
1881*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex(0), dstOffsetModified, extents,
1882*8975f5c5SAndroid Build Coastguard Worker imageType);
1883*8975f5c5SAndroid Build Coastguard Worker }
1884*8975f5c5SAndroid Build Coastguard Worker
1885*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1886*8975f5c5SAndroid Build Coastguard Worker }
1887*8975f5c5SAndroid Build Coastguard Worker
setStorageImpl(ContextVk * contextVk,gl::TextureType type,const vk::Format & format)1888*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorageImpl(ContextVk *contextVk,
1889*8975f5c5SAndroid Build Coastguard Worker gl::TextureType type,
1890*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format)
1891*8975f5c5SAndroid Build Coastguard Worker {
1892*8975f5c5SAndroid Build Coastguard Worker if (!mOwnsImage)
1893*8975f5c5SAndroid Build Coastguard Worker {
1894*8975f5c5SAndroid Build Coastguard Worker releaseAndDeleteImageAndViews(contextVk);
1895*8975f5c5SAndroid Build Coastguard Worker }
1896*8975f5c5SAndroid Build Coastguard Worker else if (mImage)
1897*8975f5c5SAndroid Build Coastguard Worker {
1898*8975f5c5SAndroid Build Coastguard Worker if (!contextVk->hasDisplayTextureShareGroup())
1899*8975f5c5SAndroid Build Coastguard Worker {
1900*8975f5c5SAndroid Build Coastguard Worker contextVk->getShareGroup()->onTextureRelease(this);
1901*8975f5c5SAndroid Build Coastguard Worker }
1902*8975f5c5SAndroid Build Coastguard Worker mImage->releaseStagedUpdates(contextVk->getRenderer());
1903*8975f5c5SAndroid Build Coastguard Worker }
1904*8975f5c5SAndroid Build Coastguard Worker
1905*8975f5c5SAndroid Build Coastguard Worker // Assume all multisample texture types must be renderable.
1906*8975f5c5SAndroid Build Coastguard Worker if (type == gl::TextureType::_2DMultisample || type == gl::TextureType::_2DMultisampleArray)
1907*8975f5c5SAndroid Build Coastguard Worker {
1908*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderableWithFormat(contextVk, format, nullptr));
1909*8975f5c5SAndroid Build Coastguard Worker }
1910*8975f5c5SAndroid Build Coastguard Worker
1911*8975f5c5SAndroid Build Coastguard Worker // Fixed rate compression
1912*8975f5c5SAndroid Build Coastguard Worker if (mState.getSurfaceCompressionFixedRate() != GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)
1913*8975f5c5SAndroid Build Coastguard Worker {
1914*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderableWithFormat(contextVk, format, nullptr));
1915*8975f5c5SAndroid Build Coastguard Worker }
1916*8975f5c5SAndroid Build Coastguard Worker
1917*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageAllocated(contextVk, format));
1918*8975f5c5SAndroid Build Coastguard Worker
1919*8975f5c5SAndroid Build Coastguard Worker if (mImage->valid())
1920*8975f5c5SAndroid Build Coastguard Worker {
1921*8975f5c5SAndroid Build Coastguard Worker releaseImage(contextVk);
1922*8975f5c5SAndroid Build Coastguard Worker }
1923*8975f5c5SAndroid Build Coastguard Worker
1924*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.getImmutableFormat());
1925*8975f5c5SAndroid Build Coastguard Worker ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
1926*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
1927*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(getRequiredImageAccess()),
1928*8975f5c5SAndroid Build Coastguard Worker ImageMipLevels::FullMipChainForGenerateMipmap));
1929*8975f5c5SAndroid Build Coastguard Worker
1930*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1931*8975f5c5SAndroid Build Coastguard Worker }
1932*8975f5c5SAndroid Build Coastguard Worker
setStorage(const gl::Context * context,gl::TextureType type,size_t levels,GLenum internalFormat,const gl::Extents & size)1933*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorage(const gl::Context *context,
1934*8975f5c5SAndroid Build Coastguard Worker gl::TextureType type,
1935*8975f5c5SAndroid Build Coastguard Worker size_t levels,
1936*8975f5c5SAndroid Build Coastguard Worker GLenum internalFormat,
1937*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size)
1938*8975f5c5SAndroid Build Coastguard Worker {
1939*8975f5c5SAndroid Build Coastguard Worker return setStorageMultisample(context, type, 1, internalFormat, size, true);
1940*8975f5c5SAndroid Build Coastguard Worker }
1941*8975f5c5SAndroid Build Coastguard Worker
setStorageMultisample(const gl::Context * context,gl::TextureType type,GLsizei samples,GLint internalformat,const gl::Extents & size,bool fixedSampleLocations)1942*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorageMultisample(const gl::Context *context,
1943*8975f5c5SAndroid Build Coastguard Worker gl::TextureType type,
1944*8975f5c5SAndroid Build Coastguard Worker GLsizei samples,
1945*8975f5c5SAndroid Build Coastguard Worker GLint internalformat,
1946*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size,
1947*8975f5c5SAndroid Build Coastguard Worker bool fixedSampleLocations)
1948*8975f5c5SAndroid Build Coastguard Worker {
1949*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = GetAs<ContextVk>(context->getImplementation());
1950*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
1951*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = renderer->getFormat(internalformat);
1952*8975f5c5SAndroid Build Coastguard Worker
1953*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setStorageImpl(contextVk, type, format));
1954*8975f5c5SAndroid Build Coastguard Worker
1955*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1956*8975f5c5SAndroid Build Coastguard Worker }
1957*8975f5c5SAndroid Build Coastguard Worker
setStorageExternalMemory(const gl::Context * context,gl::TextureType type,size_t levels,GLenum internalFormat,const gl::Extents & size,gl::MemoryObject * memoryObject,GLuint64 offset,GLbitfield createFlags,GLbitfield usageFlags,const void * imageCreateInfoPNext)1958*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorageExternalMemory(const gl::Context *context,
1959*8975f5c5SAndroid Build Coastguard Worker gl::TextureType type,
1960*8975f5c5SAndroid Build Coastguard Worker size_t levels,
1961*8975f5c5SAndroid Build Coastguard Worker GLenum internalFormat,
1962*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size,
1963*8975f5c5SAndroid Build Coastguard Worker gl::MemoryObject *memoryObject,
1964*8975f5c5SAndroid Build Coastguard Worker GLuint64 offset,
1965*8975f5c5SAndroid Build Coastguard Worker GLbitfield createFlags,
1966*8975f5c5SAndroid Build Coastguard Worker GLbitfield usageFlags,
1967*8975f5c5SAndroid Build Coastguard Worker const void *imageCreateInfoPNext)
1968*8975f5c5SAndroid Build Coastguard Worker {
1969*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
1970*8975f5c5SAndroid Build Coastguard Worker MemoryObjectVk *memoryObjectVk = vk::GetImpl(memoryObject);
1971*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
1972*8975f5c5SAndroid Build Coastguard Worker
1973*8975f5c5SAndroid Build Coastguard Worker const vk::Format &vkFormat = renderer->getFormat(internalFormat);
1974*8975f5c5SAndroid Build Coastguard Worker angle::FormatID actualFormatID = vkFormat.getActualRenderableImageFormatID();
1975*8975f5c5SAndroid Build Coastguard Worker
1976*8975f5c5SAndroid Build Coastguard Worker releaseAndDeleteImageAndViews(contextVk);
1977*8975f5c5SAndroid Build Coastguard Worker
1978*8975f5c5SAndroid Build Coastguard Worker setImageHelper(contextVk, new vk::ImageHelper(), gl::TextureType::InvalidEnum, 0, 0, true, {});
1979*8975f5c5SAndroid Build Coastguard Worker
1980*8975f5c5SAndroid Build Coastguard Worker mImage->setTilingMode(gl_vk::GetTilingMode(mState.getTilingMode()));
1981*8975f5c5SAndroid Build Coastguard Worker
1982*8975f5c5SAndroid Build Coastguard Worker // EXT_external_objects issue 13 says that all supported usage flags must be specified.
1983*8975f5c5SAndroid Build Coastguard Worker // However, ANGLE_external_objects_flags allows these flags to be masked. Note that the GL enum
1984*8975f5c5SAndroid Build Coastguard Worker // values constituting the bits of |usageFlags| are identical to their corresponding Vulkan
1985*8975f5c5SAndroid Build Coastguard Worker // value.
1986*8975f5c5SAndroid Build Coastguard Worker usageFlags &= vk::GetMaximalImageUsageFlags(renderer, actualFormatID);
1987*8975f5c5SAndroid Build Coastguard Worker
1988*8975f5c5SAndroid Build Coastguard Worker // Similarly, createFlags is restricted to what is valid.
1989*8975f5c5SAndroid Build Coastguard Worker createFlags &= vk::GetMinimalImageCreateFlags(renderer, type, usageFlags) |
1990*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
1991*8975f5c5SAndroid Build Coastguard Worker
1992*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(memoryObjectVk->createImage(contextVk, type, levels, internalFormat, size, offset,
1993*8975f5c5SAndroid Build Coastguard Worker mImage, createFlags, usageFlags, imageCreateInfoPNext));
1994*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags = usageFlags;
1995*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags = createFlags;
1996*8975f5c5SAndroid Build Coastguard Worker
1997*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageUsageFlags kRenderableUsageFlags =
1998*8975f5c5SAndroid Build Coastguard Worker kColorAttachmentImageFlags | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1999*8975f5c5SAndroid Build Coastguard Worker if ((usageFlags & kRenderableUsageFlags) != 0)
2000*8975f5c5SAndroid Build Coastguard Worker {
2001*8975f5c5SAndroid Build Coastguard Worker mRequiredImageAccess = vk::ImageAccess::Renderable;
2002*8975f5c5SAndroid Build Coastguard Worker }
2003*8975f5c5SAndroid Build Coastguard Worker
2004*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));
2005*8975f5c5SAndroid Build Coastguard Worker
2006*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2007*8975f5c5SAndroid Build Coastguard Worker }
2008*8975f5c5SAndroid Build Coastguard Worker
setStorageAttribs(const gl::Context * context,gl::TextureType type,size_t levels,GLint internalformat,const gl::Extents & size,const GLint * attribList)2009*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorageAttribs(const gl::Context *context,
2010*8975f5c5SAndroid Build Coastguard Worker gl::TextureType type,
2011*8975f5c5SAndroid Build Coastguard Worker size_t levels,
2012*8975f5c5SAndroid Build Coastguard Worker GLint internalformat,
2013*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size,
2014*8975f5c5SAndroid Build Coastguard Worker const GLint *attribList)
2015*8975f5c5SAndroid Build Coastguard Worker {
2016*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = GetAs<ContextVk>(context->getImplementation());
2017*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2018*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = renderer->getFormat(internalformat);
2019*8975f5c5SAndroid Build Coastguard Worker
2020*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setStorageImpl(contextVk, type, format));
2021*8975f5c5SAndroid Build Coastguard Worker
2022*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2023*8975f5c5SAndroid Build Coastguard Worker }
2024*8975f5c5SAndroid Build Coastguard Worker
getImageCompressionRate(const gl::Context * context)2025*8975f5c5SAndroid Build Coastguard Worker GLint TextureVk::getImageCompressionRate(const gl::Context *context)
2026*8975f5c5SAndroid Build Coastguard Worker {
2027*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
2028*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2029*8975f5c5SAndroid Build Coastguard Worker
2030*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage != nullptr && mImage->valid());
2031*8975f5c5SAndroid Build Coastguard Worker ASSERT(renderer->getFeatures().supportsImageCompressionControl.enabled);
2032*8975f5c5SAndroid Build Coastguard Worker
2033*8975f5c5SAndroid Build Coastguard Worker if (!mOwnsImage)
2034*8975f5c5SAndroid Build Coastguard Worker {
2035*8975f5c5SAndroid Build Coastguard Worker return 0;
2036*8975f5c5SAndroid Build Coastguard Worker }
2037*8975f5c5SAndroid Build Coastguard Worker
2038*8975f5c5SAndroid Build Coastguard Worker VkImageSubresource2EXT imageSubresource2 = {};
2039*8975f5c5SAndroid Build Coastguard Worker imageSubresource2.sType = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT;
2040*8975f5c5SAndroid Build Coastguard Worker imageSubresource2.imageSubresource.aspectMask = mImage->getAspectFlags();
2041*8975f5c5SAndroid Build Coastguard Worker
2042*8975f5c5SAndroid Build Coastguard Worker VkImageCompressionPropertiesEXT compressionProperties = {};
2043*8975f5c5SAndroid Build Coastguard Worker compressionProperties.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;
2044*8975f5c5SAndroid Build Coastguard Worker VkSubresourceLayout2EXT subresourceLayout = {};
2045*8975f5c5SAndroid Build Coastguard Worker subresourceLayout.sType = VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT;
2046*8975f5c5SAndroid Build Coastguard Worker subresourceLayout.pNext = &compressionProperties;
2047*8975f5c5SAndroid Build Coastguard Worker
2048*8975f5c5SAndroid Build Coastguard Worker vkGetImageSubresourceLayout2EXT(renderer->getDevice(), mImage->getImage().getHandle(),
2049*8975f5c5SAndroid Build Coastguard Worker &imageSubresource2, &subresourceLayout);
2050*8975f5c5SAndroid Build Coastguard Worker
2051*8975f5c5SAndroid Build Coastguard Worker GLint compressionRate;
2052*8975f5c5SAndroid Build Coastguard Worker // For an existing image, should only report one compression rate
2053*8975f5c5SAndroid Build Coastguard Worker vk_gl::convertCompressionFlagsToGLFixedRates(
2054*8975f5c5SAndroid Build Coastguard Worker compressionProperties.imageCompressionFixedRateFlags, 1, &compressionRate);
2055*8975f5c5SAndroid Build Coastguard Worker return compressionRate;
2056*8975f5c5SAndroid Build Coastguard Worker }
2057*8975f5c5SAndroid Build Coastguard Worker
getFormatSupportedCompressionRatesImpl(vk::Renderer * renderer,const vk::Format & format,GLsizei bufSize,GLint * rates)2058*8975f5c5SAndroid Build Coastguard Worker GLint TextureVk::getFormatSupportedCompressionRatesImpl(vk::Renderer *renderer,
2059*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format,
2060*8975f5c5SAndroid Build Coastguard Worker GLsizei bufSize,
2061*8975f5c5SAndroid Build Coastguard Worker GLint *rates)
2062*8975f5c5SAndroid Build Coastguard Worker {
2063*8975f5c5SAndroid Build Coastguard Worker if (renderer->getFeatures().supportsImageCompressionControl.enabled)
2064*8975f5c5SAndroid Build Coastguard Worker {
2065*8975f5c5SAndroid Build Coastguard Worker VkImageCompressionControlEXT compressionInfo = {};
2066*8975f5c5SAndroid Build Coastguard Worker compressionInfo.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
2067*8975f5c5SAndroid Build Coastguard Worker // Use default compression control flag for query
2068*8975f5c5SAndroid Build Coastguard Worker compressionInfo.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
2069*8975f5c5SAndroid Build Coastguard Worker
2070*8975f5c5SAndroid Build Coastguard Worker VkImageCompressionPropertiesEXT compressionProp = {};
2071*8975f5c5SAndroid Build Coastguard Worker compressionProp.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;
2072*8975f5c5SAndroid Build Coastguard Worker
2073*8975f5c5SAndroid Build Coastguard Worker if (vk::ImageHelper::FormatSupportsUsage(
2074*8975f5c5SAndroid Build Coastguard Worker renderer,
2075*8975f5c5SAndroid Build Coastguard Worker vk::GetVkFormatFromFormatID(renderer, format.getActualRenderableImageFormatID()),
2076*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
2077*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
2078*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
2079*8975f5c5SAndroid Build Coastguard Worker 0, &compressionInfo, &compressionProp,
2080*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess))
2081*8975f5c5SAndroid Build Coastguard Worker {
2082*8975f5c5SAndroid Build Coastguard Worker if ((compressionProp.imageCompressionFlags &
2083*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT) != 0)
2084*8975f5c5SAndroid Build Coastguard Worker {
2085*8975f5c5SAndroid Build Coastguard Worker return vk_gl::convertCompressionFlagsToGLFixedRates(
2086*8975f5c5SAndroid Build Coastguard Worker compressionProp.imageCompressionFixedRateFlags, bufSize, rates);
2087*8975f5c5SAndroid Build Coastguard Worker }
2088*8975f5c5SAndroid Build Coastguard Worker }
2089*8975f5c5SAndroid Build Coastguard Worker }
2090*8975f5c5SAndroid Build Coastguard Worker
2091*8975f5c5SAndroid Build Coastguard Worker return 0;
2092*8975f5c5SAndroid Build Coastguard Worker }
2093*8975f5c5SAndroid Build Coastguard Worker
getFormatSupportedCompressionRates(const gl::Context * context,GLenum internalformat,GLsizei bufSize,GLint * rates)2094*8975f5c5SAndroid Build Coastguard Worker GLint TextureVk::getFormatSupportedCompressionRates(const gl::Context *context,
2095*8975f5c5SAndroid Build Coastguard Worker GLenum internalformat,
2096*8975f5c5SAndroid Build Coastguard Worker GLsizei bufSize,
2097*8975f5c5SAndroid Build Coastguard Worker GLint *rates)
2098*8975f5c5SAndroid Build Coastguard Worker {
2099*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
2100*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2101*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = renderer->getFormat(internalformat);
2102*8975f5c5SAndroid Build Coastguard Worker
2103*8975f5c5SAndroid Build Coastguard Worker return getFormatSupportedCompressionRatesImpl(renderer, format, bufSize, rates);
2104*8975f5c5SAndroid Build Coastguard Worker }
2105*8975f5c5SAndroid Build Coastguard Worker
handleImmutableSamplerTransition(const vk::ImageHelper * previousImage,const vk::ImageHelper * nextImage)2106*8975f5c5SAndroid Build Coastguard Worker void TextureVk::handleImmutableSamplerTransition(const vk::ImageHelper *previousImage,
2107*8975f5c5SAndroid Build Coastguard Worker const vk::ImageHelper *nextImage)
2108*8975f5c5SAndroid Build Coastguard Worker {
2109*8975f5c5SAndroid Build Coastguard Worker // Did the previous image have an immutable sampler
2110*8975f5c5SAndroid Build Coastguard Worker bool previousImageHadImmutableSampler =
2111*8975f5c5SAndroid Build Coastguard Worker previousImage && previousImage->valid() && previousImage->hasImmutableSampler();
2112*8975f5c5SAndroid Build Coastguard Worker
2113*8975f5c5SAndroid Build Coastguard Worker // Does the next image require an immutable sampler?
2114*8975f5c5SAndroid Build Coastguard Worker bool nextImageRequiresImmutableSampler =
2115*8975f5c5SAndroid Build Coastguard Worker nextImage && nextImage->valid() && nextImage->hasImmutableSampler();
2116*8975f5c5SAndroid Build Coastguard Worker
2117*8975f5c5SAndroid Build Coastguard Worker // Has the external format changed?
2118*8975f5c5SAndroid Build Coastguard Worker bool externalFormatChanged = false;
2119*8975f5c5SAndroid Build Coastguard Worker if (previousImageHadImmutableSampler && nextImageRequiresImmutableSampler)
2120*8975f5c5SAndroid Build Coastguard Worker {
2121*8975f5c5SAndroid Build Coastguard Worker externalFormatChanged =
2122*8975f5c5SAndroid Build Coastguard Worker previousImage->getExternalFormat() != nextImage->getExternalFormat();
2123*8975f5c5SAndroid Build Coastguard Worker }
2124*8975f5c5SAndroid Build Coastguard Worker
2125*8975f5c5SAndroid Build Coastguard Worker // Handle transition of immutable sampler state
2126*8975f5c5SAndroid Build Coastguard Worker if ((previousImageHadImmutableSampler != nextImageRequiresImmutableSampler) ||
2127*8975f5c5SAndroid Build Coastguard Worker externalFormatChanged)
2128*8975f5c5SAndroid Build Coastguard Worker {
2129*8975f5c5SAndroid Build Coastguard Worker // The immutable sampler state is dirty.
2130*8975f5c5SAndroid Build Coastguard Worker resetSampler();
2131*8975f5c5SAndroid Build Coastguard Worker mImmutableSamplerDirty = true;
2132*8975f5c5SAndroid Build Coastguard Worker }
2133*8975f5c5SAndroid Build Coastguard Worker }
2134*8975f5c5SAndroid Build Coastguard Worker
setEGLImageTarget(const gl::Context * context,gl::TextureType type,egl::Image * image)2135*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setEGLImageTarget(const gl::Context *context,
2136*8975f5c5SAndroid Build Coastguard Worker gl::TextureType type,
2137*8975f5c5SAndroid Build Coastguard Worker egl::Image *image)
2138*8975f5c5SAndroid Build Coastguard Worker {
2139*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
2140*8975f5c5SAndroid Build Coastguard Worker ImageVk *imageVk = vk::GetImpl(image);
2141*8975f5c5SAndroid Build Coastguard Worker
2142*8975f5c5SAndroid Build Coastguard Worker // Early out if we are creating TextureVk with the exact same eglImage and target/face/level to
2143*8975f5c5SAndroid Build Coastguard Worker // avoid unnecessarily dirty the state and allocating new ImageViews etc.
2144*8975f5c5SAndroid Build Coastguard Worker if (mImage == imageVk->getImage() && mEGLImageNativeType == imageVk->getImageTextureType() &&
2145*8975f5c5SAndroid Build Coastguard Worker static_cast<GLint>(mEGLImageLevelOffset) == imageVk->getImageLevel().get() &&
2146*8975f5c5SAndroid Build Coastguard Worker mEGLImageLayerOffset == imageVk->getImageLayer())
2147*8975f5c5SAndroid Build Coastguard Worker {
2148*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2149*8975f5c5SAndroid Build Coastguard Worker }
2150*8975f5c5SAndroid Build Coastguard Worker
2151*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getShareGroup()->lockDefaultContextsPriority(contextVk));
2152*8975f5c5SAndroid Build Coastguard Worker
2153*8975f5c5SAndroid Build Coastguard Worker // TODO: Textures other than EGLImage targets can have immutable samplers.
2154*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42264309
2155*8975f5c5SAndroid Build Coastguard Worker handleImmutableSamplerTransition(mImage, imageVk ? imageVk->getImage() : nullptr);
2156*8975f5c5SAndroid Build Coastguard Worker
2157*8975f5c5SAndroid Build Coastguard Worker releaseAndDeleteImageAndViews(contextVk);
2158*8975f5c5SAndroid Build Coastguard Worker
2159*8975f5c5SAndroid Build Coastguard Worker UniqueSerial siblingSerial = imageVk->generateSiblingSerial();
2160*8975f5c5SAndroid Build Coastguard Worker setImageHelper(contextVk, imageVk->getImage(), imageVk->getImageTextureType(),
2161*8975f5c5SAndroid Build Coastguard Worker imageVk->getImageLevel().get(), imageVk->getImageLayer(), false, siblingSerial);
2162*8975f5c5SAndroid Build Coastguard Worker
2163*8975f5c5SAndroid Build Coastguard Worker // Update ImageViewHelper's colorspace related state
2164*8975f5c5SAndroid Build Coastguard Worker EGLenum imageColorspaceAttribute = image->getColorspaceAttribute();
2165*8975f5c5SAndroid Build Coastguard Worker if (imageColorspaceAttribute != EGL_GL_COLORSPACE_DEFAULT_EXT)
2166*8975f5c5SAndroid Build Coastguard Worker {
2167*8975f5c5SAndroid Build Coastguard Worker egl::ImageColorspace imageColorspace =
2168*8975f5c5SAndroid Build Coastguard Worker (imageColorspaceAttribute == EGL_GL_COLORSPACE_SRGB_KHR) ? egl::ImageColorspace::SRGB
2169*8975f5c5SAndroid Build Coastguard Worker : egl::ImageColorspace::Linear;
2170*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage != nullptr);
2171*8975f5c5SAndroid Build Coastguard Worker mImageView.updateEglImageColorspace(*mImage, imageColorspace);
2172*8975f5c5SAndroid Build Coastguard Worker }
2173*8975f5c5SAndroid Build Coastguard Worker
2174*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));
2175*8975f5c5SAndroid Build Coastguard Worker
2176*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2177*8975f5c5SAndroid Build Coastguard Worker }
2178*8975f5c5SAndroid Build Coastguard Worker
setImageExternal(const gl::Context * context,gl::TextureType type,egl::Stream * stream,const egl::Stream::GLTextureDescription & desc)2179*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setImageExternal(const gl::Context *context,
2180*8975f5c5SAndroid Build Coastguard Worker gl::TextureType type,
2181*8975f5c5SAndroid Build Coastguard Worker egl::Stream *stream,
2182*8975f5c5SAndroid Build Coastguard Worker const egl::Stream::GLTextureDescription &desc)
2183*8975f5c5SAndroid Build Coastguard Worker {
2184*8975f5c5SAndroid Build Coastguard Worker ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
2185*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop;
2186*8975f5c5SAndroid Build Coastguard Worker }
2187*8975f5c5SAndroid Build Coastguard Worker
setBuffer(const gl::Context * context,GLenum internalFormat)2188*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setBuffer(const gl::Context *context, GLenum internalFormat)
2189*8975f5c5SAndroid Build Coastguard Worker {
2190*8975f5c5SAndroid Build Coastguard Worker // No longer an image
2191*8975f5c5SAndroid Build Coastguard Worker releaseAndDeleteImageAndViews(vk::GetImpl(context));
2192*8975f5c5SAndroid Build Coastguard Worker resetSampler();
2193*8975f5c5SAndroid Build Coastguard Worker
2194*8975f5c5SAndroid Build Coastguard Worker // There's nothing else to do here.
2195*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2196*8975f5c5SAndroid Build Coastguard Worker }
2197*8975f5c5SAndroid Build Coastguard Worker
getNativeImageIndex(const gl::ImageIndex & inputImageIndex) const2198*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex TextureVk::getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const
2199*8975f5c5SAndroid Build Coastguard Worker {
2200*8975f5c5SAndroid Build Coastguard Worker if (mEGLImageNativeType == gl::TextureType::InvalidEnum)
2201*8975f5c5SAndroid Build Coastguard Worker {
2202*8975f5c5SAndroid Build Coastguard Worker return inputImageIndex;
2203*8975f5c5SAndroid Build Coastguard Worker }
2204*8975f5c5SAndroid Build Coastguard Worker
2205*8975f5c5SAndroid Build Coastguard Worker // inputImageIndex can point to a specific layer, but only for non-2D textures.
2206*8975f5c5SAndroid Build Coastguard Worker // mEGLImageNativeType can be a valid type, but only for 2D textures.
2207*8975f5c5SAndroid Build Coastguard Worker // As such, both of these cannot be true at the same time.
2208*8975f5c5SAndroid Build Coastguard Worker ASSERT(!inputImageIndex.hasLayer() && inputImageIndex.getLevelIndex() == 0);
2209*8975f5c5SAndroid Build Coastguard Worker
2210*8975f5c5SAndroid Build Coastguard Worker return gl::ImageIndex::MakeFromType(mEGLImageNativeType, mEGLImageLevelOffset,
2211*8975f5c5SAndroid Build Coastguard Worker mEGLImageLayerOffset);
2212*8975f5c5SAndroid Build Coastguard Worker }
2213*8975f5c5SAndroid Build Coastguard Worker
getNativeImageLevel(gl::LevelIndex frontendLevel) const2214*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex TextureVk::getNativeImageLevel(gl::LevelIndex frontendLevel) const
2215*8975f5c5SAndroid Build Coastguard Worker {
2216*8975f5c5SAndroid Build Coastguard Worker ASSERT(frontendLevel.get() == 0 || mEGLImageLevelOffset == 0);
2217*8975f5c5SAndroid Build Coastguard Worker return frontendLevel + mEGLImageLevelOffset;
2218*8975f5c5SAndroid Build Coastguard Worker }
2219*8975f5c5SAndroid Build Coastguard Worker
getNativeImageLayer(uint32_t frontendLayer) const2220*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getNativeImageLayer(uint32_t frontendLayer) const
2221*8975f5c5SAndroid Build Coastguard Worker {
2222*8975f5c5SAndroid Build Coastguard Worker ASSERT(frontendLayer == 0 || mEGLImageLayerOffset == 0);
2223*8975f5c5SAndroid Build Coastguard Worker return frontendLayer + mEGLImageLayerOffset;
2224*8975f5c5SAndroid Build Coastguard Worker }
2225*8975f5c5SAndroid Build Coastguard Worker
releaseAndDeleteImageAndViews(ContextVk * contextVk)2226*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseAndDeleteImageAndViews(ContextVk *contextVk)
2227*8975f5c5SAndroid Build Coastguard Worker {
2228*8975f5c5SAndroid Build Coastguard Worker if (mImage)
2229*8975f5c5SAndroid Build Coastguard Worker {
2230*8975f5c5SAndroid Build Coastguard Worker if (mOwnsImage)
2231*8975f5c5SAndroid Build Coastguard Worker {
2232*8975f5c5SAndroid Build Coastguard Worker releaseStagedUpdates(contextVk);
2233*8975f5c5SAndroid Build Coastguard Worker }
2234*8975f5c5SAndroid Build Coastguard Worker releaseImage(contextVk);
2235*8975f5c5SAndroid Build Coastguard Worker mImageObserverBinding.bind(nullptr);
2236*8975f5c5SAndroid Build Coastguard Worker mRequiresMutableStorage = false;
2237*8975f5c5SAndroid Build Coastguard Worker mRequiredImageAccess = vk::ImageAccess::SampleOnly;
2238*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags = 0;
2239*8975f5c5SAndroid Build Coastguard Worker SafeDelete(mImage);
2240*8975f5c5SAndroid Build Coastguard Worker }
2241*8975f5c5SAndroid Build Coastguard Worker
2242*8975f5c5SAndroid Build Coastguard Worker if (!contextVk->hasDisplayTextureShareGroup())
2243*8975f5c5SAndroid Build Coastguard Worker {
2244*8975f5c5SAndroid Build Coastguard Worker contextVk->getShareGroup()->onTextureRelease(this);
2245*8975f5c5SAndroid Build Coastguard Worker }
2246*8975f5c5SAndroid Build Coastguard Worker
2247*8975f5c5SAndroid Build Coastguard Worker if (getBuffer().get() != nullptr)
2248*8975f5c5SAndroid Build Coastguard Worker {
2249*8975f5c5SAndroid Build Coastguard Worker mBufferContentsObservers->disableForBuffer(getBuffer().get());
2250*8975f5c5SAndroid Build Coastguard Worker }
2251*8975f5c5SAndroid Build Coastguard Worker
2252*8975f5c5SAndroid Build Coastguard Worker if (mBufferViews.isInitialized())
2253*8975f5c5SAndroid Build Coastguard Worker {
2254*8975f5c5SAndroid Build Coastguard Worker mBufferViews.release(contextVk);
2255*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectChanged);
2256*8975f5c5SAndroid Build Coastguard Worker }
2257*8975f5c5SAndroid Build Coastguard Worker mRedefinedLevels = {};
2258*8975f5c5SAndroid Build Coastguard Worker mDescriptorSetCacheManager.releaseKeys(contextVk->getRenderer());
2259*8975f5c5SAndroid Build Coastguard Worker }
2260*8975f5c5SAndroid Build Coastguard Worker
initImageUsageFlags(ContextVk * contextVk,angle::FormatID actualFormatID)2261*8975f5c5SAndroid Build Coastguard Worker void TextureVk::initImageUsageFlags(ContextVk *contextVk, angle::FormatID actualFormatID)
2262*8975f5c5SAndroid Build Coastguard Worker {
2263*8975f5c5SAndroid Build Coastguard Worker ASSERT(actualFormatID != angle::FormatID::NONE);
2264*8975f5c5SAndroid Build Coastguard Worker
2265*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags = kTransferImageFlags | VK_IMAGE_USAGE_SAMPLED_BIT;
2266*8975f5c5SAndroid Build Coastguard Worker
2267*8975f5c5SAndroid Build Coastguard Worker // If the image has depth/stencil support, add those as possible usage.
2268*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2269*8975f5c5SAndroid Build Coastguard Worker if (angle::Format::Get(actualFormatID).hasDepthOrStencilBits())
2270*8975f5c5SAndroid Build Coastguard Worker {
2271*8975f5c5SAndroid Build Coastguard Worker // Work around a bug in the Mock ICD:
2272*8975f5c5SAndroid Build Coastguard Worker // https://github.com/KhronosGroup/Vulkan-Tools/issues/445
2273*8975f5c5SAndroid Build Coastguard Worker if (renderer->hasImageFormatFeatureBits(actualFormatID,
2274*8975f5c5SAndroid Build Coastguard Worker VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
2275*8975f5c5SAndroid Build Coastguard Worker {
2276*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
2277*8975f5c5SAndroid Build Coastguard Worker
2278*8975f5c5SAndroid Build Coastguard Worker if (renderer->getFeatures().supportsShaderFramebufferFetchDepthStencil.enabled)
2279*8975f5c5SAndroid Build Coastguard Worker {
2280*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
2281*8975f5c5SAndroid Build Coastguard Worker }
2282*8975f5c5SAndroid Build Coastguard Worker }
2283*8975f5c5SAndroid Build Coastguard Worker }
2284*8975f5c5SAndroid Build Coastguard Worker else if (renderer->hasImageFormatFeatureBits(actualFormatID,
2285*8975f5c5SAndroid Build Coastguard Worker VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
2286*8975f5c5SAndroid Build Coastguard Worker {
2287*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags |= kColorAttachmentImageFlags;
2288*8975f5c5SAndroid Build Coastguard Worker }
2289*8975f5c5SAndroid Build Coastguard Worker }
2290*8975f5c5SAndroid Build Coastguard Worker
ensureImageAllocated(ContextVk * contextVk,const vk::Format & format)2291*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureImageAllocated(ContextVk *contextVk, const vk::Format &format)
2292*8975f5c5SAndroid Build Coastguard Worker {
2293*8975f5c5SAndroid Build Coastguard Worker if (mImage == nullptr)
2294*8975f5c5SAndroid Build Coastguard Worker {
2295*8975f5c5SAndroid Build Coastguard Worker setImageHelper(contextVk, new vk::ImageHelper(), gl::TextureType::InvalidEnum, 0, 0, true,
2296*8975f5c5SAndroid Build Coastguard Worker {});
2297*8975f5c5SAndroid Build Coastguard Worker }
2298*8975f5c5SAndroid Build Coastguard Worker
2299*8975f5c5SAndroid Build Coastguard Worker initImageUsageFlags(contextVk, format.getActualImageFormatID(getRequiredImageAccess()));
2300*8975f5c5SAndroid Build Coastguard Worker
2301*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2302*8975f5c5SAndroid Build Coastguard Worker }
2303*8975f5c5SAndroid Build Coastguard Worker
setImageHelper(ContextVk * contextVk,vk::ImageHelper * imageHelper,gl::TextureType eglImageNativeType,uint32_t imageLevelOffset,uint32_t imageLayerOffset,bool selfOwned,UniqueSerial siblingSerial)2304*8975f5c5SAndroid Build Coastguard Worker void TextureVk::setImageHelper(ContextVk *contextVk,
2305*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *imageHelper,
2306*8975f5c5SAndroid Build Coastguard Worker gl::TextureType eglImageNativeType,
2307*8975f5c5SAndroid Build Coastguard Worker uint32_t imageLevelOffset,
2308*8975f5c5SAndroid Build Coastguard Worker uint32_t imageLayerOffset,
2309*8975f5c5SAndroid Build Coastguard Worker bool selfOwned,
2310*8975f5c5SAndroid Build Coastguard Worker UniqueSerial siblingSerial)
2311*8975f5c5SAndroid Build Coastguard Worker {
2312*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage == nullptr);
2313*8975f5c5SAndroid Build Coastguard Worker
2314*8975f5c5SAndroid Build Coastguard Worker mImageObserverBinding.bind(imageHelper);
2315*8975f5c5SAndroid Build Coastguard Worker
2316*8975f5c5SAndroid Build Coastguard Worker ASSERT(selfOwned == !siblingSerial.valid());
2317*8975f5c5SAndroid Build Coastguard Worker mOwnsImage = selfOwned;
2318*8975f5c5SAndroid Build Coastguard Worker mImageSiblingSerial = siblingSerial;
2319*8975f5c5SAndroid Build Coastguard Worker // If image is shared between other container objects, force it to renderable format since we
2320*8975f5c5SAndroid Build Coastguard Worker // don't know if other container object will render or not.
2321*8975f5c5SAndroid Build Coastguard Worker if (!mOwnsImage && !imageHelper->isBackedByExternalMemory())
2322*8975f5c5SAndroid Build Coastguard Worker {
2323*8975f5c5SAndroid Build Coastguard Worker mRequiredImageAccess = vk::ImageAccess::Renderable;
2324*8975f5c5SAndroid Build Coastguard Worker }
2325*8975f5c5SAndroid Build Coastguard Worker mEGLImageNativeType = eglImageNativeType;
2326*8975f5c5SAndroid Build Coastguard Worker mEGLImageLevelOffset = imageLevelOffset;
2327*8975f5c5SAndroid Build Coastguard Worker mEGLImageLayerOffset = imageLayerOffset;
2328*8975f5c5SAndroid Build Coastguard Worker mImage = imageHelper;
2329*8975f5c5SAndroid Build Coastguard Worker
2330*8975f5c5SAndroid Build Coastguard Worker // All render targets must be already destroyed prior to this call.
2331*8975f5c5SAndroid Build Coastguard Worker for (auto &renderTargets : mSingleLayerRenderTargets)
2332*8975f5c5SAndroid Build Coastguard Worker {
2333*8975f5c5SAndroid Build Coastguard Worker ASSERT(renderTargets.empty());
2334*8975f5c5SAndroid Build Coastguard Worker }
2335*8975f5c5SAndroid Build Coastguard Worker ASSERT(mMultiLayerRenderTargets.empty());
2336*8975f5c5SAndroid Build Coastguard Worker
2337*8975f5c5SAndroid Build Coastguard Worker if (!selfOwned)
2338*8975f5c5SAndroid Build Coastguard Worker {
2339*8975f5c5SAndroid Build Coastguard Worker // (!selfOwned) implies that the texture is a target sibling.
2340*8975f5c5SAndroid Build Coastguard Worker // Inherit a few VkImage's create attributes from ImageHelper.
2341*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags = mImage->getCreateFlags();
2342*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags = mImage->getUsage();
2343*8975f5c5SAndroid Build Coastguard Worker mRequiresMutableStorage = (mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0;
2344*8975f5c5SAndroid Build Coastguard Worker }
2345*8975f5c5SAndroid Build Coastguard Worker
2346*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2347*8975f5c5SAndroid Build Coastguard Worker
2348*8975f5c5SAndroid Build Coastguard Worker getImageViews().init(renderer);
2349*8975f5c5SAndroid Build Coastguard Worker }
2350*8975f5c5SAndroid Build Coastguard Worker
redefineLevel(const gl::Context * context,const gl::ImageIndex & index,const vk::Format & format,const gl::Extents & size)2351*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::redefineLevel(const gl::Context *context,
2352*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index,
2353*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format,
2354*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size)
2355*8975f5c5SAndroid Build Coastguard Worker {
2356*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
2357*8975f5c5SAndroid Build Coastguard Worker
2358*8975f5c5SAndroid Build Coastguard Worker if (!mOwnsImage)
2359*8975f5c5SAndroid Build Coastguard Worker {
2360*8975f5c5SAndroid Build Coastguard Worker releaseAndDeleteImageAndViews(contextVk);
2361*8975f5c5SAndroid Build Coastguard Worker }
2362*8975f5c5SAndroid Build Coastguard Worker
2363*8975f5c5SAndroid Build Coastguard Worker if (mImage != nullptr)
2364*8975f5c5SAndroid Build Coastguard Worker {
2365*8975f5c5SAndroid Build Coastguard Worker // If there are any staged changes for this index, we can remove them since we're going to
2366*8975f5c5SAndroid Build Coastguard Worker // override them with this call.
2367*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex levelIndexGL(index.getLevelIndex());
2368*8975f5c5SAndroid Build Coastguard Worker const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
2369*8975f5c5SAndroid Build Coastguard Worker if (gl::IsArrayTextureType(index.getType()))
2370*8975f5c5SAndroid Build Coastguard Worker {
2371*8975f5c5SAndroid Build Coastguard Worker // A multi-layer texture is being redefined, remove all updates to this level; the
2372*8975f5c5SAndroid Build Coastguard Worker // number of layers may have changed.
2373*8975f5c5SAndroid Build Coastguard Worker mImage->removeStagedUpdates(contextVk, levelIndexGL, levelIndexGL);
2374*8975f5c5SAndroid Build Coastguard Worker }
2375*8975f5c5SAndroid Build Coastguard Worker else
2376*8975f5c5SAndroid Build Coastguard Worker {
2377*8975f5c5SAndroid Build Coastguard Worker // Otherwise remove only updates to this layer. For example, cube map updates can be
2378*8975f5c5SAndroid Build Coastguard Worker // done through glTexImage2D, one per cube face (i.e. layer) and so should not remove
2379*8975f5c5SAndroid Build Coastguard Worker // updates to the other layers.
2380*8975f5c5SAndroid Build Coastguard Worker ASSERT(index.getLayerCount() == 1);
2381*8975f5c5SAndroid Build Coastguard Worker mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
2382*8975f5c5SAndroid Build Coastguard Worker index.getLayerCount());
2383*8975f5c5SAndroid Build Coastguard Worker }
2384*8975f5c5SAndroid Build Coastguard Worker
2385*8975f5c5SAndroid Build Coastguard Worker if (mImage->valid())
2386*8975f5c5SAndroid Build Coastguard Worker {
2387*8975f5c5SAndroid Build Coastguard Worker TextureLevelAllocation levelAllocation =
2388*8975f5c5SAndroid Build Coastguard Worker IsTextureLevelInAllocatedImage(*mImage, levelIndexGL)
2389*8975f5c5SAndroid Build Coastguard Worker ? TextureLevelAllocation::WithinAllocatedImage
2390*8975f5c5SAndroid Build Coastguard Worker : TextureLevelAllocation::OutsideAllocatedImage;
2391*8975f5c5SAndroid Build Coastguard Worker TextureLevelDefinition levelDefinition =
2392*8975f5c5SAndroid Build Coastguard Worker IsTextureLevelDefinitionCompatibleWithImage(
2393*8975f5c5SAndroid Build Coastguard Worker *mImage, levelIndexGL, size, format.getIntendedFormatID(),
2394*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(getRequiredImageAccess()))
2395*8975f5c5SAndroid Build Coastguard Worker ? TextureLevelDefinition::Compatible
2396*8975f5c5SAndroid Build Coastguard Worker : TextureLevelDefinition::Incompatible;
2397*8975f5c5SAndroid Build Coastguard Worker if (TextureRedefineLevel(levelAllocation, levelDefinition, mState.getImmutableFormat(),
2398*8975f5c5SAndroid Build Coastguard Worker mImage->getLevelCount(), layerIndex, index,
2399*8975f5c5SAndroid Build Coastguard Worker mImage->getFirstAllocatedLevel(), &mRedefinedLevels))
2400*8975f5c5SAndroid Build Coastguard Worker {
2401*8975f5c5SAndroid Build Coastguard Worker releaseImage(contextVk);
2402*8975f5c5SAndroid Build Coastguard Worker }
2403*8975f5c5SAndroid Build Coastguard Worker }
2404*8975f5c5SAndroid Build Coastguard Worker }
2405*8975f5c5SAndroid Build Coastguard Worker
2406*8975f5c5SAndroid Build Coastguard Worker // If image is not released due to an out-of-range or incompatible level definition, the image
2407*8975f5c5SAndroid Build Coastguard Worker // is still valid and we shouldn't redefine it to use the new format. In that case,
2408*8975f5c5SAndroid Build Coastguard Worker // ensureImageAllocated will only use the format to update the staging buffer's alignment to
2409*8975f5c5SAndroid Build Coastguard Worker // support both the previous and the new formats.
2410*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageAllocated(contextVk, format));
2411*8975f5c5SAndroid Build Coastguard Worker
2412*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2413*8975f5c5SAndroid Build Coastguard Worker }
2414*8975f5c5SAndroid Build Coastguard Worker
copyImageDataToBufferAndGetData(ContextVk * contextVk,gl::LevelIndex sourceLevelGL,uint32_t layerCount,const gl::Box & sourceArea,RenderPassClosureReason reason,vk::BufferHelper * copyBuffer,uint8_t ** outDataPtr)2415*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyImageDataToBufferAndGetData(ContextVk *contextVk,
2416*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex sourceLevelGL,
2417*8975f5c5SAndroid Build Coastguard Worker uint32_t layerCount,
2418*8975f5c5SAndroid Build Coastguard Worker const gl::Box &sourceArea,
2419*8975f5c5SAndroid Build Coastguard Worker RenderPassClosureReason reason,
2420*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper *copyBuffer,
2421*8975f5c5SAndroid Build Coastguard Worker uint8_t **outDataPtr)
2422*8975f5c5SAndroid Build Coastguard Worker {
2423*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyImageDataToBufferAndGetData");
2424*8975f5c5SAndroid Build Coastguard Worker
2425*8975f5c5SAndroid Build Coastguard Worker // Make sure the source is initialized and it's images are flushed.
2426*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
2427*8975f5c5SAndroid Build Coastguard Worker
2428*8975f5c5SAndroid Build Coastguard Worker gl::Box modifiedSourceArea = sourceArea;
2429*8975f5c5SAndroid Build Coastguard Worker
2430*8975f5c5SAndroid Build Coastguard Worker bool is3D = mImage->getExtents().depth > 1;
2431*8975f5c5SAndroid Build Coastguard Worker if (is3D)
2432*8975f5c5SAndroid Build Coastguard Worker {
2433*8975f5c5SAndroid Build Coastguard Worker layerCount = 1;
2434*8975f5c5SAndroid Build Coastguard Worker }
2435*8975f5c5SAndroid Build Coastguard Worker else
2436*8975f5c5SAndroid Build Coastguard Worker {
2437*8975f5c5SAndroid Build Coastguard Worker modifiedSourceArea.depth = 1;
2438*8975f5c5SAndroid Build Coastguard Worker }
2439*8975f5c5SAndroid Build Coastguard Worker
2440*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, sourceLevelGL, layerCount, 0,
2441*8975f5c5SAndroid Build Coastguard Worker modifiedSourceArea, copyBuffer, outDataPtr));
2442*8975f5c5SAndroid Build Coastguard Worker
2443*8975f5c5SAndroid Build Coastguard Worker // Explicitly finish. If new use cases arise where we don't want to block we can change this.
2444*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->finishImpl(reason));
2445*8975f5c5SAndroid Build Coastguard Worker // invalidate must be called after wait for finish.
2446*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(copyBuffer->invalidate(contextVk->getRenderer()));
2447*8975f5c5SAndroid Build Coastguard Worker
2448*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2449*8975f5c5SAndroid Build Coastguard Worker }
2450*8975f5c5SAndroid Build Coastguard Worker
copyBufferDataToImage(ContextVk * contextVk,vk::BufferHelper * srcBuffer,const gl::ImageIndex index,uint32_t rowLength,uint32_t imageHeight,const gl::Box & sourceArea,size_t offset,VkImageAspectFlags aspectFlags)2451*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyBufferDataToImage(ContextVk *contextVk,
2452*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper *srcBuffer,
2453*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex index,
2454*8975f5c5SAndroid Build Coastguard Worker uint32_t rowLength,
2455*8975f5c5SAndroid Build Coastguard Worker uint32_t imageHeight,
2456*8975f5c5SAndroid Build Coastguard Worker const gl::Box &sourceArea,
2457*8975f5c5SAndroid Build Coastguard Worker size_t offset,
2458*8975f5c5SAndroid Build Coastguard Worker VkImageAspectFlags aspectFlags)
2459*8975f5c5SAndroid Build Coastguard Worker {
2460*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyBufferDataToImage");
2461*8975f5c5SAndroid Build Coastguard Worker
2462*8975f5c5SAndroid Build Coastguard Worker // Vulkan Spec requires the bufferOffset to be a multiple of pixel size for
2463*8975f5c5SAndroid Build Coastguard Worker // vkCmdCopyBufferToImage.
2464*8975f5c5SAndroid Build Coastguard Worker ASSERT((offset % vk::GetImageCopyBufferAlignment(mImage->getActualFormatID())) == 0);
2465*8975f5c5SAndroid Build Coastguard Worker
2466*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex level = gl::LevelIndex(index.getLevelIndex());
2467*8975f5c5SAndroid Build Coastguard Worker GLuint layerCount = index.getLayerCount();
2468*8975f5c5SAndroid Build Coastguard Worker GLuint layerIndex = 0;
2469*8975f5c5SAndroid Build Coastguard Worker
2470*8975f5c5SAndroid Build Coastguard Worker ASSERT((aspectFlags & kDepthStencilAspects) != kDepthStencilAspects);
2471*8975f5c5SAndroid Build Coastguard Worker
2472*8975f5c5SAndroid Build Coastguard Worker VkBufferImageCopy region = {};
2473*8975f5c5SAndroid Build Coastguard Worker region.bufferOffset = offset;
2474*8975f5c5SAndroid Build Coastguard Worker region.bufferRowLength = rowLength;
2475*8975f5c5SAndroid Build Coastguard Worker region.bufferImageHeight = imageHeight;
2476*8975f5c5SAndroid Build Coastguard Worker region.imageExtent.width = sourceArea.width;
2477*8975f5c5SAndroid Build Coastguard Worker region.imageExtent.height = sourceArea.height;
2478*8975f5c5SAndroid Build Coastguard Worker region.imageExtent.depth = sourceArea.depth;
2479*8975f5c5SAndroid Build Coastguard Worker region.imageOffset.x = sourceArea.x;
2480*8975f5c5SAndroid Build Coastguard Worker region.imageOffset.y = sourceArea.y;
2481*8975f5c5SAndroid Build Coastguard Worker region.imageOffset.z = sourceArea.z;
2482*8975f5c5SAndroid Build Coastguard Worker region.imageSubresource.aspectMask = aspectFlags;
2483*8975f5c5SAndroid Build Coastguard Worker region.imageSubresource.layerCount = layerCount;
2484*8975f5c5SAndroid Build Coastguard Worker region.imageSubresource.mipLevel = mImage->toVkLevel(level).get();
2485*8975f5c5SAndroid Build Coastguard Worker
2486*8975f5c5SAndroid Build Coastguard Worker if (gl::IsArrayTextureType(index.getType()))
2487*8975f5c5SAndroid Build Coastguard Worker {
2488*8975f5c5SAndroid Build Coastguard Worker layerIndex = sourceArea.z;
2489*8975f5c5SAndroid Build Coastguard Worker region.imageOffset.z = 0;
2490*8975f5c5SAndroid Build Coastguard Worker region.imageExtent.depth = 1;
2491*8975f5c5SAndroid Build Coastguard Worker }
2492*8975f5c5SAndroid Build Coastguard Worker else if (index.getType() == gl::TextureType::CubeMap)
2493*8975f5c5SAndroid Build Coastguard Worker {
2494*8975f5c5SAndroid Build Coastguard Worker // Copy to the correct cube map face.
2495*8975f5c5SAndroid Build Coastguard Worker layerIndex = index.getLayerIndex();
2496*8975f5c5SAndroid Build Coastguard Worker }
2497*8975f5c5SAndroid Build Coastguard Worker region.imageSubresource.baseArrayLayer = layerIndex;
2498*8975f5c5SAndroid Build Coastguard Worker
2499*8975f5c5SAndroid Build Coastguard Worker // Make sure the source is initialized and its images are flushed.
2500*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
2501*8975f5c5SAndroid Build Coastguard Worker
2502*8975f5c5SAndroid Build Coastguard Worker vk::CommandBufferAccess access;
2503*8975f5c5SAndroid Build Coastguard Worker access.onBufferTransferRead(srcBuffer);
2504*8975f5c5SAndroid Build Coastguard Worker access.onImageTransferWrite(level, 1, layerIndex, layerCount, mImage->getAspectFlags(), mImage);
2505*8975f5c5SAndroid Build Coastguard Worker
2506*8975f5c5SAndroid Build Coastguard Worker vk::OutsideRenderPassCommandBuffer *commandBuffer;
2507*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2508*8975f5c5SAndroid Build Coastguard Worker
2509*8975f5c5SAndroid Build Coastguard Worker commandBuffer->copyBufferToImage(srcBuffer->getBuffer().getHandle(), mImage->getImage(),
2510*8975f5c5SAndroid Build Coastguard Worker mImage->getCurrentLayout(contextVk->getRenderer()), 1,
2511*8975f5c5SAndroid Build Coastguard Worker ®ion);
2512*8975f5c5SAndroid Build Coastguard Worker
2513*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2514*8975f5c5SAndroid Build Coastguard Worker }
2515*8975f5c5SAndroid Build Coastguard Worker
generateMipmapsWithCompute(ContextVk * contextVk)2516*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
2517*8975f5c5SAndroid Build Coastguard Worker {
2518*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2519*8975f5c5SAndroid Build Coastguard Worker
2520*8975f5c5SAndroid Build Coastguard Worker // Requires that the image:
2521*8975f5c5SAndroid Build Coastguard Worker //
2522*8975f5c5SAndroid Build Coastguard Worker // - is not sRGB
2523*8975f5c5SAndroid Build Coastguard Worker // - is not integer
2524*8975f5c5SAndroid Build Coastguard Worker // - is 2D or 2D array
2525*8975f5c5SAndroid Build Coastguard Worker // - is single sample
2526*8975f5c5SAndroid Build Coastguard Worker // - is color image
2527*8975f5c5SAndroid Build Coastguard Worker //
2528*8975f5c5SAndroid Build Coastguard Worker // Support for the first two can be added easily. Supporting 3D textures, MSAA and
2529*8975f5c5SAndroid Build Coastguard Worker // depth/stencil would be more involved.
2530*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mImage->getActualFormat().isSRGB);
2531*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mImage->getActualFormat().isInt());
2532*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->getType() == VK_IMAGE_TYPE_2D);
2533*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->getSamples() == 1);
2534*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->getAspectFlags() == VK_IMAGE_ASPECT_COLOR_BIT);
2535*8975f5c5SAndroid Build Coastguard Worker
2536*8975f5c5SAndroid Build Coastguard Worker // Create the appropriate sampler.
2537*8975f5c5SAndroid Build Coastguard Worker GLenum filter = CalculateGenerateMipmapFilter(contextVk, mImage->getActualFormatID());
2538*8975f5c5SAndroid Build Coastguard Worker
2539*8975f5c5SAndroid Build Coastguard Worker gl::SamplerState samplerState;
2540*8975f5c5SAndroid Build Coastguard Worker samplerState.setMinFilter(filter);
2541*8975f5c5SAndroid Build Coastguard Worker samplerState.setMagFilter(filter);
2542*8975f5c5SAndroid Build Coastguard Worker samplerState.setWrapS(GL_CLAMP_TO_EDGE);
2543*8975f5c5SAndroid Build Coastguard Worker samplerState.setWrapT(GL_CLAMP_TO_EDGE);
2544*8975f5c5SAndroid Build Coastguard Worker samplerState.setWrapR(GL_CLAMP_TO_EDGE);
2545*8975f5c5SAndroid Build Coastguard Worker
2546*8975f5c5SAndroid Build Coastguard Worker vk::SharedSamplerPtr sampler;
2547*8975f5c5SAndroid Build Coastguard Worker vk::SamplerDesc samplerDesc(contextVk, samplerState, false, nullptr,
2548*8975f5c5SAndroid Build Coastguard Worker static_cast<angle::FormatID>(0));
2549*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));
2550*8975f5c5SAndroid Build Coastguard Worker
2551*8975f5c5SAndroid Build Coastguard Worker // If the image has more levels than supported, generate as many mips as possible at a time.
2552*8975f5c5SAndroid Build Coastguard Worker const vk::LevelIndex maxGenerateLevels(UtilsVk::GetGenerateMipmapMaxLevels(contextVk));
2553*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex dstMaxLevelVk = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel()));
2554*8975f5c5SAndroid Build Coastguard Worker for (vk::LevelIndex dstBaseLevelVk =
2555*8975f5c5SAndroid Build Coastguard Worker mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel() + 1));
2556*8975f5c5SAndroid Build Coastguard Worker dstBaseLevelVk <= dstMaxLevelVk; dstBaseLevelVk = dstBaseLevelVk + maxGenerateLevels.get())
2557*8975f5c5SAndroid Build Coastguard Worker {
2558*8975f5c5SAndroid Build Coastguard Worker vk::CommandBufferAccess access;
2559*8975f5c5SAndroid Build Coastguard Worker
2560*8975f5c5SAndroid Build Coastguard Worker // For mipmap generation, we should make sure that there is no pending write for the source
2561*8975f5c5SAndroid Build Coastguard Worker // mip level. If there is, a barrier should be inserted before the source mip being used.
2562*8975f5c5SAndroid Build Coastguard Worker const vk::LevelIndex srcLevelVk = dstBaseLevelVk - 1;
2563*8975f5c5SAndroid Build Coastguard Worker uint32_t writeLevelCount =
2564*8975f5c5SAndroid Build Coastguard Worker std::min(maxGenerateLevels.get(), dstMaxLevelVk.get() + 1 - dstBaseLevelVk.get());
2565*8975f5c5SAndroid Build Coastguard Worker
2566*8975f5c5SAndroid Build Coastguard Worker access.onImageComputeMipmapGenerationRead(mImage->toGLLevel(srcLevelVk), 1, 0,
2567*8975f5c5SAndroid Build Coastguard Worker mImage->getLayerCount(),
2568*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_ASPECT_COLOR_BIT, mImage);
2569*8975f5c5SAndroid Build Coastguard Worker access.onImageComputeShaderWrite(mImage->toGLLevel(dstBaseLevelVk), writeLevelCount, 0,
2570*8975f5c5SAndroid Build Coastguard Worker mImage->getLayerCount(), VK_IMAGE_ASPECT_COLOR_BIT,
2571*8975f5c5SAndroid Build Coastguard Worker mImage);
2572*8975f5c5SAndroid Build Coastguard Worker
2573*8975f5c5SAndroid Build Coastguard Worker vk::OutsideRenderPassCommandBuffer *commandBuffer;
2574*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2575*8975f5c5SAndroid Build Coastguard Worker
2576*8975f5c5SAndroid Build Coastguard Worker // Generate mipmaps for every layer separately.
2577*8975f5c5SAndroid Build Coastguard Worker for (uint32_t layer = 0; layer < mImage->getLayerCount(); ++layer)
2578*8975f5c5SAndroid Build Coastguard Worker {
2579*8975f5c5SAndroid Build Coastguard Worker // Create the necessary views.
2580*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView *srcView = nullptr;
2581*8975f5c5SAndroid Build Coastguard Worker UtilsVk::GenerateMipmapDestLevelViews destLevelViews = {};
2582*8975f5c5SAndroid Build Coastguard Worker
2583*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getImageViews().getLevelLayerDrawImageView(contextVk, *mImage, srcLevelVk,
2584*8975f5c5SAndroid Build Coastguard Worker layer, &srcView));
2585*8975f5c5SAndroid Build Coastguard Worker
2586*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex dstLevelCount = maxGenerateLevels;
2587*8975f5c5SAndroid Build Coastguard Worker for (vk::LevelIndex levelVk(0); levelVk < maxGenerateLevels; ++levelVk)
2588*8975f5c5SAndroid Build Coastguard Worker {
2589*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex dstLevelVk = dstBaseLevelVk + levelVk.get();
2590*8975f5c5SAndroid Build Coastguard Worker
2591*8975f5c5SAndroid Build Coastguard Worker // If fewer levels left than maxGenerateLevels, cut the loop short.
2592*8975f5c5SAndroid Build Coastguard Worker if (dstLevelVk > dstMaxLevelVk)
2593*8975f5c5SAndroid Build Coastguard Worker {
2594*8975f5c5SAndroid Build Coastguard Worker dstLevelCount = levelVk;
2595*8975f5c5SAndroid Build Coastguard Worker break;
2596*8975f5c5SAndroid Build Coastguard Worker }
2597*8975f5c5SAndroid Build Coastguard Worker
2598*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getImageViews().getLevelLayerDrawImageView(
2599*8975f5c5SAndroid Build Coastguard Worker contextVk, *mImage, dstLevelVk, layer, &destLevelViews[levelVk.get()]));
2600*8975f5c5SAndroid Build Coastguard Worker }
2601*8975f5c5SAndroid Build Coastguard Worker
2602*8975f5c5SAndroid Build Coastguard Worker // If the image has fewer than maximum levels, fill the last views with a unused view.
2603*8975f5c5SAndroid Build Coastguard Worker ASSERT(dstLevelCount > vk::LevelIndex(0));
2604*8975f5c5SAndroid Build Coastguard Worker for (vk::LevelIndex levelVk = dstLevelCount;
2605*8975f5c5SAndroid Build Coastguard Worker levelVk < vk::LevelIndex(UtilsVk::kGenerateMipmapMaxLevels); ++levelVk)
2606*8975f5c5SAndroid Build Coastguard Worker {
2607*8975f5c5SAndroid Build Coastguard Worker destLevelViews[levelVk.get()] = destLevelViews[levelVk.get() - 1];
2608*8975f5c5SAndroid Build Coastguard Worker }
2609*8975f5c5SAndroid Build Coastguard Worker
2610*8975f5c5SAndroid Build Coastguard Worker // Generate mipmaps.
2611*8975f5c5SAndroid Build Coastguard Worker UtilsVk::GenerateMipmapParameters params = {};
2612*8975f5c5SAndroid Build Coastguard Worker params.srcLevel = srcLevelVk.get();
2613*8975f5c5SAndroid Build Coastguard Worker params.dstLevelCount = dstLevelCount.get();
2614*8975f5c5SAndroid Build Coastguard Worker
2615*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getUtils().generateMipmap(contextVk, mImage, srcView, mImage,
2616*8975f5c5SAndroid Build Coastguard Worker destLevelViews, sampler->get(), params));
2617*8975f5c5SAndroid Build Coastguard Worker }
2618*8975f5c5SAndroid Build Coastguard Worker }
2619*8975f5c5SAndroid Build Coastguard Worker
2620*8975f5c5SAndroid Build Coastguard Worker contextVk->trackImageWithOutsideRenderPassEvent(mImage);
2621*8975f5c5SAndroid Build Coastguard Worker
2622*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2623*8975f5c5SAndroid Build Coastguard Worker }
2624*8975f5c5SAndroid Build Coastguard Worker
generateMipmapsWithCPU(const gl::Context * context)2625*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
2626*8975f5c5SAndroid Build Coastguard Worker {
2627*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
2628*8975f5c5SAndroid Build Coastguard Worker
2629*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex baseLevelGL(mState.getEffectiveBaseLevel());
2630*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex baseLevelVk = mImage->toVkLevel(baseLevelGL);
2631*8975f5c5SAndroid Build Coastguard Worker const gl::Extents baseLevelExtents = mImage->getLevelExtents(baseLevelVk);
2632*8975f5c5SAndroid Build Coastguard Worker uint32_t imageLayerCount = mImage->getLayerCount();
2633*8975f5c5SAndroid Build Coastguard Worker
2634*8975f5c5SAndroid Build Coastguard Worker uint8_t *imageData = nullptr;
2635*8975f5c5SAndroid Build Coastguard Worker gl::Box imageArea(0, 0, 0, baseLevelExtents.width, baseLevelExtents.height,
2636*8975f5c5SAndroid Build Coastguard Worker baseLevelExtents.depth);
2637*8975f5c5SAndroid Build Coastguard Worker
2638*8975f5c5SAndroid Build Coastguard Worker vk::RendererScoped<vk::BufferHelper> bufferHelper(contextVk->getRenderer());
2639*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(copyImageDataToBufferAndGetData(contextVk, baseLevelGL, imageLayerCount, imageArea,
2640*8975f5c5SAndroid Build Coastguard Worker RenderPassClosureReason::GenerateMipmapOnCPU,
2641*8975f5c5SAndroid Build Coastguard Worker &bufferHelper.get(), &imageData));
2642*8975f5c5SAndroid Build Coastguard Worker
2643*8975f5c5SAndroid Build Coastguard Worker const angle::Format &angleFormat = mImage->getActualFormat();
2644*8975f5c5SAndroid Build Coastguard Worker GLuint sourceRowPitch = baseLevelExtents.width * angleFormat.pixelBytes;
2645*8975f5c5SAndroid Build Coastguard Worker GLuint sourceDepthPitch = sourceRowPitch * baseLevelExtents.height;
2646*8975f5c5SAndroid Build Coastguard Worker size_t baseLevelAllocationSize = sourceDepthPitch * baseLevelExtents.depth;
2647*8975f5c5SAndroid Build Coastguard Worker
2648*8975f5c5SAndroid Build Coastguard Worker // We now have the base level available to be manipulated in the imageData pointer. Generate all
2649*8975f5c5SAndroid Build Coastguard Worker // the missing mipmaps with the slow path. For each layer, use the copied data to generate all
2650*8975f5c5SAndroid Build Coastguard Worker // the mips.
2651*8975f5c5SAndroid Build Coastguard Worker for (GLuint layer = 0; layer < imageLayerCount; layer++)
2652*8975f5c5SAndroid Build Coastguard Worker {
2653*8975f5c5SAndroid Build Coastguard Worker size_t bufferOffset = layer * baseLevelAllocationSize;
2654*8975f5c5SAndroid Build Coastguard Worker
2655*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(generateMipmapLevelsWithCPU(contextVk, angleFormat, layer, baseLevelGL + 1,
2656*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex(mState.getMipmapMaxLevel()),
2657*8975f5c5SAndroid Build Coastguard Worker baseLevelExtents.width, baseLevelExtents.height,
2658*8975f5c5SAndroid Build Coastguard Worker baseLevelExtents.depth, sourceRowPitch,
2659*8975f5c5SAndroid Build Coastguard Worker sourceDepthPitch, imageData + bufferOffset));
2660*8975f5c5SAndroid Build Coastguard Worker }
2661*8975f5c5SAndroid Build Coastguard Worker
2662*8975f5c5SAndroid Build Coastguard Worker ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
2663*8975f5c5SAndroid Build Coastguard Worker return flushImageStagedUpdates(contextVk);
2664*8975f5c5SAndroid Build Coastguard Worker }
2665*8975f5c5SAndroid Build Coastguard Worker
generateMipmap(const gl::Context * context)2666*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::generateMipmap(const gl::Context *context)
2667*8975f5c5SAndroid Build Coastguard Worker {
2668*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
2669*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2670*8975f5c5SAndroid Build Coastguard Worker
2671*8975f5c5SAndroid Build Coastguard Worker // The image should already be allocated by a prior syncState.
2672*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->valid());
2673*8975f5c5SAndroid Build Coastguard Worker
2674*8975f5c5SAndroid Build Coastguard Worker // If base level has changed, the front-end should have called syncState already.
2675*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.getImmutableFormat() ||
2676*8975f5c5SAndroid Build Coastguard Worker mImage->getFirstAllocatedLevel() == gl::LevelIndex(mState.getEffectiveBaseLevel()));
2677*8975f5c5SAndroid Build Coastguard Worker
2678*8975f5c5SAndroid Build Coastguard Worker // Only staged update here is the robust resource init if any.
2679*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::FullMipChainForGenerateMipmap));
2680*8975f5c5SAndroid Build Coastguard Worker
2681*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex baseLevel = mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel()));
2682*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex maxLevel = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel()));
2683*8975f5c5SAndroid Build Coastguard Worker ASSERT(maxLevel != vk::LevelIndex(0));
2684*8975f5c5SAndroid Build Coastguard Worker
2685*8975f5c5SAndroid Build Coastguard Worker if (getImageViews().hasColorspaceOverrideForWrite(*mImage))
2686*8975f5c5SAndroid Build Coastguard Worker {
2687*8975f5c5SAndroid Build Coastguard Worker angle::FormatID actualFormatID =
2688*8975f5c5SAndroid Build Coastguard Worker getImageViews().getColorspaceOverrideFormatForWrite(mImage->getActualFormatID());
2689*8975f5c5SAndroid Build Coastguard Worker return contextVk->getUtils().generateMipmapWithDraw(
2690*8975f5c5SAndroid Build Coastguard Worker contextVk, mImage, actualFormatID,
2691*8975f5c5SAndroid Build Coastguard Worker gl::IsMipmapFiltered(mState.getSamplerState().getMinFilter()));
2692*8975f5c5SAndroid Build Coastguard Worker }
2693*8975f5c5SAndroid Build Coastguard Worker
2694*8975f5c5SAndroid Build Coastguard Worker // If it's possible to generate mipmap in compute, that would give the best possible
2695*8975f5c5SAndroid Build Coastguard Worker // performance on some hardware.
2696*8975f5c5SAndroid Build Coastguard Worker if (CanGenerateMipmapWithCompute(renderer, mImage->getType(), mImage->getActualFormatID(),
2697*8975f5c5SAndroid Build Coastguard Worker mImage->getSamples(), mOwnsImage))
2698*8975f5c5SAndroid Build Coastguard Worker {
2699*8975f5c5SAndroid Build Coastguard Worker ASSERT((mImageUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) != 0);
2700*8975f5c5SAndroid Build Coastguard Worker return generateMipmapsWithCompute(contextVk);
2701*8975f5c5SAndroid Build Coastguard Worker }
2702*8975f5c5SAndroid Build Coastguard Worker else if (renderer->hasImageFormatFeatureBits(mImage->getActualFormatID(), kBlitFeatureFlags))
2703*8975f5c5SAndroid Build Coastguard Worker {
2704*8975f5c5SAndroid Build Coastguard Worker // Otherwise, use blit if possible.
2705*8975f5c5SAndroid Build Coastguard Worker return mImage->generateMipmapsWithBlit(contextVk, baseLevel, maxLevel);
2706*8975f5c5SAndroid Build Coastguard Worker }
2707*8975f5c5SAndroid Build Coastguard Worker
2708*8975f5c5SAndroid Build Coastguard Worker ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
2709*8975f5c5SAndroid Build Coastguard Worker "Mipmap generated on CPU due to format restrictions");
2710*8975f5c5SAndroid Build Coastguard Worker
2711*8975f5c5SAndroid Build Coastguard Worker // If not possible to generate mipmaps on the GPU, do it on the CPU for conformance.
2712*8975f5c5SAndroid Build Coastguard Worker return generateMipmapsWithCPU(context);
2713*8975f5c5SAndroid Build Coastguard Worker }
2714*8975f5c5SAndroid Build Coastguard Worker
setBaseLevel(const gl::Context * context,GLuint baseLevel)2715*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setBaseLevel(const gl::Context *context, GLuint baseLevel)
2716*8975f5c5SAndroid Build Coastguard Worker {
2717*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2718*8975f5c5SAndroid Build Coastguard Worker }
2719*8975f5c5SAndroid Build Coastguard Worker
maybeUpdateBaseMaxLevels(ContextVk * contextVk,TextureUpdateResult * updateResultOut)2720*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::maybeUpdateBaseMaxLevels(ContextVk *contextVk,
2721*8975f5c5SAndroid Build Coastguard Worker TextureUpdateResult *updateResultOut)
2722*8975f5c5SAndroid Build Coastguard Worker {
2723*8975f5c5SAndroid Build Coastguard Worker if (!mImage)
2724*8975f5c5SAndroid Build Coastguard Worker {
2725*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2726*8975f5c5SAndroid Build Coastguard Worker }
2727*8975f5c5SAndroid Build Coastguard Worker
2728*8975f5c5SAndroid Build Coastguard Worker bool baseLevelChanged = mCurrentBaseLevel.get() != static_cast<GLint>(mState.getBaseLevel());
2729*8975f5c5SAndroid Build Coastguard Worker bool maxLevelChanged = mCurrentMaxLevel.get() != static_cast<GLint>(mState.getMaxLevel());
2730*8975f5c5SAndroid Build Coastguard Worker
2731*8975f5c5SAndroid Build Coastguard Worker if (!maxLevelChanged && !baseLevelChanged)
2732*8975f5c5SAndroid Build Coastguard Worker {
2733*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2734*8975f5c5SAndroid Build Coastguard Worker }
2735*8975f5c5SAndroid Build Coastguard Worker
2736*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex newBaseLevel = gl::LevelIndex(mState.getEffectiveBaseLevel());
2737*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex newMaxLevel = gl::LevelIndex(mState.getEffectiveMaxLevel());
2738*8975f5c5SAndroid Build Coastguard Worker ASSERT(newBaseLevel <= newMaxLevel);
2739*8975f5c5SAndroid Build Coastguard Worker
2740*8975f5c5SAndroid Build Coastguard Worker if (!mImage->valid())
2741*8975f5c5SAndroid Build Coastguard Worker {
2742*8975f5c5SAndroid Build Coastguard Worker // No further work to do, let staged updates handle the new levels
2743*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2744*8975f5c5SAndroid Build Coastguard Worker }
2745*8975f5c5SAndroid Build Coastguard Worker
2746*8975f5c5SAndroid Build Coastguard Worker if (mState.getImmutableFormat())
2747*8975f5c5SAndroid Build Coastguard Worker {
2748*8975f5c5SAndroid Build Coastguard Worker // For immutable texture, baseLevel/maxLevel should be a subset of the texture's actual
2749*8975f5c5SAndroid Build Coastguard Worker // number of mip levels. We don't need to respecify an image.
2750*8975f5c5SAndroid Build Coastguard Worker ASSERT(!baseLevelChanged || newBaseLevel >= mImage->getFirstAllocatedLevel());
2751*8975f5c5SAndroid Build Coastguard Worker ASSERT(!maxLevelChanged || newMaxLevel < gl::LevelIndex(mImage->getLevelCount()));
2752*8975f5c5SAndroid Build Coastguard Worker }
2753*8975f5c5SAndroid Build Coastguard Worker else if (!baseLevelChanged && (newMaxLevel <= mImage->getLastAllocatedLevel()))
2754*8975f5c5SAndroid Build Coastguard Worker {
2755*8975f5c5SAndroid Build Coastguard Worker // With a valid image, check if only changing the maxLevel to a subset of the texture's
2756*8975f5c5SAndroid Build Coastguard Worker // actual number of mip levels
2757*8975f5c5SAndroid Build Coastguard Worker ASSERT(maxLevelChanged);
2758*8975f5c5SAndroid Build Coastguard Worker }
2759*8975f5c5SAndroid Build Coastguard Worker else
2760*8975f5c5SAndroid Build Coastguard Worker {
2761*8975f5c5SAndroid Build Coastguard Worker *updateResultOut = TextureUpdateResult::ImageRespecified;
2762*8975f5c5SAndroid Build Coastguard Worker return respecifyImageStorage(contextVk);
2763*8975f5c5SAndroid Build Coastguard Worker }
2764*8975f5c5SAndroid Build Coastguard Worker
2765*8975f5c5SAndroid Build Coastguard Worker // Don't need to respecify the texture; but do need to update which vkImageView's are served up
2766*8975f5c5SAndroid Build Coastguard Worker // by ImageViewHelper
2767*8975f5c5SAndroid Build Coastguard Worker
2768*8975f5c5SAndroid Build Coastguard Worker // Update the current max level in ImageViewHelper
2769*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImageViews(contextVk, newMaxLevel - newBaseLevel + 1));
2770*8975f5c5SAndroid Build Coastguard Worker
2771*8975f5c5SAndroid Build Coastguard Worker mCurrentBaseLevel = newBaseLevel;
2772*8975f5c5SAndroid Build Coastguard Worker mCurrentMaxLevel = newMaxLevel;
2773*8975f5c5SAndroid Build Coastguard Worker
2774*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2775*8975f5c5SAndroid Build Coastguard Worker }
2776*8975f5c5SAndroid Build Coastguard Worker
copyAndStageImageData(ContextVk * contextVk,gl::LevelIndex previousFirstAllocateLevel,vk::ImageHelper * srcImage,vk::ImageHelper * dstImage)2777*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyAndStageImageData(ContextVk *contextVk,
2778*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex previousFirstAllocateLevel,
2779*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *srcImage,
2780*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *dstImage)
2781*8975f5c5SAndroid Build Coastguard Worker {
2782*8975f5c5SAndroid Build Coastguard Worker // Preserve the data in the Vulkan image. GL texture's staged updates that correspond to
2783*8975f5c5SAndroid Build Coastguard Worker // levels outside the range of the Vulkan image will remain intact.
2784*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2785*8975f5c5SAndroid Build Coastguard Worker
2786*8975f5c5SAndroid Build Coastguard Worker // This path is only called when switching from !owned to owned, in which case if any level was
2787*8975f5c5SAndroid Build Coastguard Worker // redefined it's already released and deleted by TextureVk::redefineLevel().
2788*8975f5c5SAndroid Build Coastguard Worker ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
2789*8975f5c5SAndroid Build Coastguard Worker
2790*8975f5c5SAndroid Build Coastguard Worker // Create a temp copy of srcImage for staging.
2791*8975f5c5SAndroid Build Coastguard Worker std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
2792*8975f5c5SAndroid Build Coastguard Worker stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();
2793*8975f5c5SAndroid Build Coastguard Worker
2794*8975f5c5SAndroid Build Coastguard Worker const uint32_t levelCount = srcImage->getLevelCount();
2795*8975f5c5SAndroid Build Coastguard Worker const uint32_t layerCount = srcImage->getLayerCount();
2796*8975f5c5SAndroid Build Coastguard Worker
2797*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(stagingImage->get().initStaging(
2798*8975f5c5SAndroid Build Coastguard Worker contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
2799*8975f5c5SAndroid Build Coastguard Worker srcImage->getType(), srcImage->getExtents(), srcImage->getIntendedFormatID(),
2800*8975f5c5SAndroid Build Coastguard Worker srcImage->getActualFormatID(), srcImage->getSamples(), kTransferImageFlags, levelCount,
2801*8975f5c5SAndroid Build Coastguard Worker layerCount));
2802*8975f5c5SAndroid Build Coastguard Worker
2803*8975f5c5SAndroid Build Coastguard Worker // Copy the src image wholly into the staging image
2804*8975f5c5SAndroid Build Coastguard Worker const VkImageAspectFlags aspectFlags = srcImage->getAspectFlags();
2805*8975f5c5SAndroid Build Coastguard Worker
2806*8975f5c5SAndroid Build Coastguard Worker vk::CommandBufferAccess access;
2807*8975f5c5SAndroid Build Coastguard Worker access.onImageTransferWrite(gl::LevelIndex(0), levelCount, 0, layerCount, aspectFlags,
2808*8975f5c5SAndroid Build Coastguard Worker &stagingImage->get());
2809*8975f5c5SAndroid Build Coastguard Worker access.onImageTransferRead(aspectFlags, srcImage);
2810*8975f5c5SAndroid Build Coastguard Worker
2811*8975f5c5SAndroid Build Coastguard Worker vk::OutsideRenderPassCommandBuffer *commandBuffer;
2812*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2813*8975f5c5SAndroid Build Coastguard Worker
2814*8975f5c5SAndroid Build Coastguard Worker VkImageCopy copyRegion = {};
2815*8975f5c5SAndroid Build Coastguard Worker copyRegion.srcSubresource.aspectMask = aspectFlags;
2816*8975f5c5SAndroid Build Coastguard Worker copyRegion.srcSubresource.layerCount = layerCount;
2817*8975f5c5SAndroid Build Coastguard Worker copyRegion.dstSubresource = copyRegion.srcSubresource;
2818*8975f5c5SAndroid Build Coastguard Worker
2819*8975f5c5SAndroid Build Coastguard Worker for (vk::LevelIndex levelVk(0); levelVk < vk::LevelIndex(levelCount); ++levelVk)
2820*8975f5c5SAndroid Build Coastguard Worker {
2821*8975f5c5SAndroid Build Coastguard Worker gl::Extents levelExtents = srcImage->getLevelExtents(levelVk);
2822*8975f5c5SAndroid Build Coastguard Worker
2823*8975f5c5SAndroid Build Coastguard Worker copyRegion.srcSubresource.mipLevel = levelVk.get();
2824*8975f5c5SAndroid Build Coastguard Worker copyRegion.dstSubresource.mipLevel = levelVk.get();
2825*8975f5c5SAndroid Build Coastguard Worker gl_vk::GetExtent(levelExtents, ©Region.extent);
2826*8975f5c5SAndroid Build Coastguard Worker
2827*8975f5c5SAndroid Build Coastguard Worker commandBuffer->copyImage(srcImage->getImage(), srcImage->getCurrentLayout(renderer),
2828*8975f5c5SAndroid Build Coastguard Worker stagingImage->get().getImage(),
2829*8975f5c5SAndroid Build Coastguard Worker stagingImage->get().getCurrentLayout(renderer), 1, ©Region);
2830*8975f5c5SAndroid Build Coastguard Worker }
2831*8975f5c5SAndroid Build Coastguard Worker
2832*8975f5c5SAndroid Build Coastguard Worker // Stage the staging image in the destination
2833*8975f5c5SAndroid Build Coastguard Worker dstImage->stageSubresourceUpdatesFromAllImageLevels(stagingImage.release(),
2834*8975f5c5SAndroid Build Coastguard Worker previousFirstAllocateLevel);
2835*8975f5c5SAndroid Build Coastguard Worker
2836*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2837*8975f5c5SAndroid Build Coastguard Worker }
2838*8975f5c5SAndroid Build Coastguard Worker
reinitImageAsRenderable(ContextVk * contextVk,const vk::Format & format)2839*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk, const vk::Format &format)
2840*8975f5c5SAndroid Build Coastguard Worker {
2841*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->valid());
2842*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
2843*8975f5c5SAndroid Build Coastguard Worker
2844*8975f5c5SAndroid Build Coastguard Worker const uint32_t levelCount = mImage->getLevelCount();
2845*8975f5c5SAndroid Build Coastguard Worker const uint32_t layerCount = mImage->getLayerCount();
2846*8975f5c5SAndroid Build Coastguard Worker
2847*8975f5c5SAndroid Build Coastguard Worker // Make sure the source is initialized and its staged updates are flushed.
2848*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(flushImageStagedUpdates(contextVk));
2849*8975f5c5SAndroid Build Coastguard Worker
2850*8975f5c5SAndroid Build Coastguard Worker const angle::Format &srcFormat = mImage->getActualFormat();
2851*8975f5c5SAndroid Build Coastguard Worker const angle::Format &dstFormat = format.getActualImageFormat(getRequiredImageAccess());
2852*8975f5c5SAndroid Build Coastguard Worker
2853*8975f5c5SAndroid Build Coastguard Worker // If layerCount or levelCount is bigger than 1, we go for the slow path for now. The problem
2854*8975f5c5SAndroid Build Coastguard Worker // with draw path is that in the multiple level/layer case, we have to do copy in a loop.
2855*8975f5c5SAndroid Build Coastguard Worker // Currently copySubImageImplWithDraw() calls ensureImageInitalized which forces flush out
2856*8975f5c5SAndroid Build Coastguard Worker // staged updates that we just staged inside the loop which is wrong.
2857*8975f5c5SAndroid Build Coastguard Worker if (levelCount == 1 && layerCount == 1 &&
2858*8975f5c5SAndroid Build Coastguard Worker !IsTextureLevelRedefined(mRedefinedLevels, mState.getType(),
2859*8975f5c5SAndroid Build Coastguard Worker mImage->getFirstAllocatedLevel()))
2860*8975f5c5SAndroid Build Coastguard Worker {
2861*8975f5c5SAndroid Build Coastguard Worker ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW,
2862*8975f5c5SAndroid Build Coastguard Worker "Copying image data due to texture format fallback");
2863*8975f5c5SAndroid Build Coastguard Worker
2864*8975f5c5SAndroid Build Coastguard Worker ASSERT(CanCopyWithDraw(renderer, mImage->getActualFormatID(), mImage->getTilingMode(),
2865*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(getRequiredImageAccess()),
2866*8975f5c5SAndroid Build Coastguard Worker getTilingMode()));
2867*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex levelVk(0);
2868*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex sourceLevelGL = mImage->toGLLevel(levelVk);
2869*8975f5c5SAndroid Build Coastguard Worker gl::Box sourceBox(gl::kOffsetZero, mImage->getLevelExtents(levelVk));
2870*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex index =
2871*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex::MakeFromType(mState.getType(), sourceLevelGL.get());
2872*8975f5c5SAndroid Build Coastguard Worker
2873*8975f5c5SAndroid Build Coastguard Worker // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
2874*8975f5c5SAndroid Build Coastguard Worker // Otherwise the view serials would not reflect the render pass they are really used in.
2875*8975f5c5SAndroid Build Coastguard Worker // http://crbug.com/1272266#c22
2876*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
2877*8975f5c5SAndroid Build Coastguard Worker contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));
2878*8975f5c5SAndroid Build Coastguard Worker
2879*8975f5c5SAndroid Build Coastguard Worker return copySubImageImplWithDraw(contextVk, index, gl::kOffsetZero, format, sourceLevelGL,
2880*8975f5c5SAndroid Build Coastguard Worker sourceBox, false, false, false, false, mImage,
2881*8975f5c5SAndroid Build Coastguard Worker &getCopyImageView(), SurfaceRotation::Identity);
2882*8975f5c5SAndroid Build Coastguard Worker }
2883*8975f5c5SAndroid Build Coastguard Worker
2884*8975f5c5SAndroid Build Coastguard Worker for (vk::LevelIndex levelVk(0); levelVk < vk::LevelIndex(levelCount); ++levelVk)
2885*8975f5c5SAndroid Build Coastguard Worker {
2886*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex levelGL = mImage->toGLLevel(levelVk);
2887*8975f5c5SAndroid Build Coastguard Worker if (IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), levelGL))
2888*8975f5c5SAndroid Build Coastguard Worker {
2889*8975f5c5SAndroid Build Coastguard Worker continue;
2890*8975f5c5SAndroid Build Coastguard Worker }
2891*8975f5c5SAndroid Build Coastguard Worker
2892*8975f5c5SAndroid Build Coastguard Worker ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
2893*8975f5c5SAndroid Build Coastguard Worker "GPU stall due to texture format fallback");
2894*8975f5c5SAndroid Build Coastguard Worker
2895*8975f5c5SAndroid Build Coastguard Worker gl::Box sourceBox(gl::kOffsetZero, mImage->getLevelExtents(levelVk));
2896*8975f5c5SAndroid Build Coastguard Worker // copy and stage entire layer
2897*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex index =
2898*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex::MakeFromType(mState.getType(), levelGL.get(), 0, layerCount);
2899*8975f5c5SAndroid Build Coastguard Worker
2900*8975f5c5SAndroid Build Coastguard Worker // Read back the requested region of the source texture
2901*8975f5c5SAndroid Build Coastguard Worker vk::RendererScoped<vk::BufferHelper> bufferHelper(renderer);
2902*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper *srcBuffer = &bufferHelper.get();
2903*8975f5c5SAndroid Build Coastguard Worker uint8_t *srcData = nullptr;
2904*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, levelGL, layerCount, 0, sourceBox,
2905*8975f5c5SAndroid Build Coastguard Worker srcBuffer, &srcData));
2906*8975f5c5SAndroid Build Coastguard Worker
2907*8975f5c5SAndroid Build Coastguard Worker // Explicitly finish. If new use cases arise where we don't want to block we can change
2908*8975f5c5SAndroid Build Coastguard Worker // this.
2909*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->finishImpl(RenderPassClosureReason::TextureReformatToRenderable));
2910*8975f5c5SAndroid Build Coastguard Worker // invalidate must be called after wait for finish.
2911*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(srcBuffer->invalidate(renderer));
2912*8975f5c5SAndroid Build Coastguard Worker
2913*8975f5c5SAndroid Build Coastguard Worker size_t dstBufferSize = sourceBox.width * sourceBox.height * sourceBox.depth *
2914*8975f5c5SAndroid Build Coastguard Worker dstFormat.pixelBytes * layerCount;
2915*8975f5c5SAndroid Build Coastguard Worker
2916*8975f5c5SAndroid Build Coastguard Worker // Allocate memory in the destination texture for the copy/conversion.
2917*8975f5c5SAndroid Build Coastguard Worker uint8_t *dstData = nullptr;
2918*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
2919*8975f5c5SAndroid Build Coastguard Worker contextVk, dstBufferSize, index, mImage->getLevelExtents(levelVk), gl::kOffsetZero,
2920*8975f5c5SAndroid Build Coastguard Worker &dstData, dstFormat.id));
2921*8975f5c5SAndroid Build Coastguard Worker
2922*8975f5c5SAndroid Build Coastguard Worker // Source and destination data is tightly packed
2923*8975f5c5SAndroid Build Coastguard Worker GLuint srcDataRowPitch = sourceBox.width * srcFormat.pixelBytes;
2924*8975f5c5SAndroid Build Coastguard Worker GLuint dstDataRowPitch = sourceBox.width * dstFormat.pixelBytes;
2925*8975f5c5SAndroid Build Coastguard Worker
2926*8975f5c5SAndroid Build Coastguard Worker GLuint srcDataDepthPitch = srcDataRowPitch * sourceBox.height;
2927*8975f5c5SAndroid Build Coastguard Worker GLuint dstDataDepthPitch = dstDataRowPitch * sourceBox.height;
2928*8975f5c5SAndroid Build Coastguard Worker
2929*8975f5c5SAndroid Build Coastguard Worker GLuint srcDataLayerPitch = srcDataDepthPitch * sourceBox.depth;
2930*8975f5c5SAndroid Build Coastguard Worker GLuint dstDataLayerPitch = dstDataDepthPitch * sourceBox.depth;
2931*8975f5c5SAndroid Build Coastguard Worker
2932*8975f5c5SAndroid Build Coastguard Worker rx::PixelReadFunction pixelReadFunction = srcFormat.pixelReadFunction;
2933*8975f5c5SAndroid Build Coastguard Worker rx::PixelWriteFunction pixelWriteFunction = dstFormat.pixelWriteFunction;
2934*8975f5c5SAndroid Build Coastguard Worker
2935*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &dstFormatInfo = *mState.getImageDesc(index).format.info;
2936*8975f5c5SAndroid Build Coastguard Worker for (uint32_t layer = 0; layer < layerCount; layer++)
2937*8975f5c5SAndroid Build Coastguard Worker {
2938*8975f5c5SAndroid Build Coastguard Worker CopyImageCHROMIUM(srcData + layer * srcDataLayerPitch, srcDataRowPitch,
2939*8975f5c5SAndroid Build Coastguard Worker srcFormat.pixelBytes, srcDataDepthPitch, pixelReadFunction,
2940*8975f5c5SAndroid Build Coastguard Worker dstData + layer * dstDataLayerPitch, dstDataRowPitch,
2941*8975f5c5SAndroid Build Coastguard Worker dstFormat.pixelBytes, dstDataDepthPitch, pixelWriteFunction,
2942*8975f5c5SAndroid Build Coastguard Worker dstFormatInfo.format, dstFormatInfo.componentType, sourceBox.width,
2943*8975f5c5SAndroid Build Coastguard Worker sourceBox.height, sourceBox.depth, false, false, false);
2944*8975f5c5SAndroid Build Coastguard Worker }
2945*8975f5c5SAndroid Build Coastguard Worker }
2946*8975f5c5SAndroid Build Coastguard Worker
2947*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2948*8975f5c5SAndroid Build Coastguard Worker }
2949*8975f5c5SAndroid Build Coastguard Worker
respecifyImageStorage(ContextVk * contextVk)2950*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::respecifyImageStorage(ContextVk *contextVk)
2951*8975f5c5SAndroid Build Coastguard Worker {
2952*8975f5c5SAndroid Build Coastguard Worker if (!mImage->valid())
2953*8975f5c5SAndroid Build Coastguard Worker {
2954*8975f5c5SAndroid Build Coastguard Worker ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
2955*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2956*8975f5c5SAndroid Build Coastguard Worker }
2957*8975f5c5SAndroid Build Coastguard Worker
2958*8975f5c5SAndroid Build Coastguard Worker // Recreate the image to reflect new base or max levels.
2959*8975f5c5SAndroid Build Coastguard Worker // First, flush any pending updates so we have good data in the current mImage
2960*8975f5c5SAndroid Build Coastguard Worker if (mImage->hasStagedUpdatesInAllocatedLevels())
2961*8975f5c5SAndroid Build Coastguard Worker {
2962*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(flushImageStagedUpdates(contextVk));
2963*8975f5c5SAndroid Build Coastguard Worker }
2964*8975f5c5SAndroid Build Coastguard Worker
2965*8975f5c5SAndroid Build Coastguard Worker if (!mOwnsImage)
2966*8975f5c5SAndroid Build Coastguard Worker {
2967*8975f5c5SAndroid Build Coastguard Worker // Cache values needed for copy and stage operations
2968*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *srcImage = mImage;
2969*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
2970*8975f5c5SAndroid Build Coastguard Worker
2971*8975f5c5SAndroid Build Coastguard Worker // If any level was redefined but the image was not owned by the Texture, it's already
2972*8975f5c5SAndroid Build Coastguard Worker // released and deleted by TextureVk::redefineLevel().
2973*8975f5c5SAndroid Build Coastguard Worker ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
2974*8975f5c5SAndroid Build Coastguard Worker
2975*8975f5c5SAndroid Build Coastguard Worker // Save previousFirstAllocateLevel before mImage becomes invalid
2976*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex previousFirstAllocateLevel = mImage->getFirstAllocatedLevel();
2977*8975f5c5SAndroid Build Coastguard Worker
2978*8975f5c5SAndroid Build Coastguard Worker // If we didn't own the image, release the current and create a new one
2979*8975f5c5SAndroid Build Coastguard Worker releaseImage(contextVk);
2980*8975f5c5SAndroid Build Coastguard Worker
2981*8975f5c5SAndroid Build Coastguard Worker // Create the image helper
2982*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageAllocated(contextVk, format));
2983*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
2984*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(getRequiredImageAccess()),
2985*8975f5c5SAndroid Build Coastguard Worker mState.getImmutableFormat()
2986*8975f5c5SAndroid Build Coastguard Worker ? ImageMipLevels::FullMipChainForGenerateMipmap
2987*8975f5c5SAndroid Build Coastguard Worker : ImageMipLevels::EnabledLevels));
2988*8975f5c5SAndroid Build Coastguard Worker
2989*8975f5c5SAndroid Build Coastguard Worker // Make a copy of the old image (that's being released) and stage that as an update to the
2990*8975f5c5SAndroid Build Coastguard Worker // new image.
2991*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(copyAndStageImageData(contextVk, previousFirstAllocateLevel, srcImage, mImage));
2992*8975f5c5SAndroid Build Coastguard Worker }
2993*8975f5c5SAndroid Build Coastguard Worker else
2994*8975f5c5SAndroid Build Coastguard Worker {
2995*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
2996*8975f5c5SAndroid Build Coastguard Worker if (mImage->getActualFormatID() != format.getActualImageFormatID(getRequiredImageAccess()))
2997*8975f5c5SAndroid Build Coastguard Worker {
2998*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(reinitImageAsRenderable(contextVk, format));
2999*8975f5c5SAndroid Build Coastguard Worker }
3000*8975f5c5SAndroid Build Coastguard Worker else
3001*8975f5c5SAndroid Build Coastguard Worker {
3002*8975f5c5SAndroid Build Coastguard Worker stageSelfAsSubresourceUpdates(contextVk);
3003*8975f5c5SAndroid Build Coastguard Worker }
3004*8975f5c5SAndroid Build Coastguard Worker // Release the current image so that it will be recreated with the correct number of mip
3005*8975f5c5SAndroid Build Coastguard Worker // levels, base level, and max level.
3006*8975f5c5SAndroid Build Coastguard Worker releaseImage(contextVk);
3007*8975f5c5SAndroid Build Coastguard Worker }
3008*8975f5c5SAndroid Build Coastguard Worker
3009*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3010*8975f5c5SAndroid Build Coastguard Worker }
3011*8975f5c5SAndroid Build Coastguard Worker
bindTexImage(const gl::Context * context,egl::Surface * surface)3012*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::bindTexImage(const gl::Context *context, egl::Surface *surface)
3013*8975f5c5SAndroid Build Coastguard Worker {
3014*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
3015*8975f5c5SAndroid Build Coastguard Worker
3016*8975f5c5SAndroid Build Coastguard Worker releaseAndDeleteImageAndViews(contextVk);
3017*8975f5c5SAndroid Build Coastguard Worker
3018*8975f5c5SAndroid Build Coastguard Worker // eglBindTexImage can only be called with pbuffer (offscreen) surfaces
3019*8975f5c5SAndroid Build Coastguard Worker OffscreenSurfaceVk *offscreenSurface = GetImplAs<OffscreenSurfaceVk>(surface);
3020*8975f5c5SAndroid Build Coastguard Worker // Surface can only have single target. Just generate valid serial with throw-away generator.
3021*8975f5c5SAndroid Build Coastguard Worker UniqueSerial siblingSerial = UniqueSerialFactory().generate();
3022*8975f5c5SAndroid Build Coastguard Worker setImageHelper(contextVk, offscreenSurface->getColorAttachmentImage(),
3023*8975f5c5SAndroid Build Coastguard Worker gl::TextureType::InvalidEnum, 0, 0, false, siblingSerial);
3024*8975f5c5SAndroid Build Coastguard Worker
3025*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->getLayerCount() == 1);
3026*8975f5c5SAndroid Build Coastguard Worker return initImageViews(contextVk, getImageViewLevelCount());
3027*8975f5c5SAndroid Build Coastguard Worker }
3028*8975f5c5SAndroid Build Coastguard Worker
releaseTexImage(const gl::Context * context)3029*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::releaseTexImage(const gl::Context *context)
3030*8975f5c5SAndroid Build Coastguard Worker {
3031*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
3032*8975f5c5SAndroid Build Coastguard Worker
3033*8975f5c5SAndroid Build Coastguard Worker releaseImage(contextVk);
3034*8975f5c5SAndroid Build Coastguard Worker
3035*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3036*8975f5c5SAndroid Build Coastguard Worker }
3037*8975f5c5SAndroid Build Coastguard Worker
getAttachmentRenderTarget(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex,GLsizei samples,FramebufferAttachmentRenderTarget ** rtOut)3038*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
3039*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
3040*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex,
3041*8975f5c5SAndroid Build Coastguard Worker GLsizei samples,
3042*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentRenderTarget **rtOut)
3043*8975f5c5SAndroid Build Coastguard Worker {
3044*8975f5c5SAndroid Build Coastguard Worker GLint requestedLevel = imageIndex.getLevelIndex();
3045*8975f5c5SAndroid Build Coastguard Worker ASSERT(requestedLevel >= 0);
3046*8975f5c5SAndroid Build Coastguard Worker
3047*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
3048*8975f5c5SAndroid Build Coastguard Worker
3049*8975f5c5SAndroid Build Coastguard Worker // Sync the texture's image. See comment on this function in the header.
3050*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(respecifyImageStorageIfNecessary(contextVk, gl::Command::Draw));
3051*8975f5c5SAndroid Build Coastguard Worker
3052*8975f5c5SAndroid Build Coastguard Worker // Don't flush staged updates here. We'll handle that in FramebufferVk so we can defer clears.
3053*8975f5c5SAndroid Build Coastguard Worker
3054*8975f5c5SAndroid Build Coastguard Worker if (!mImage->valid())
3055*8975f5c5SAndroid Build Coastguard Worker {
3056*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
3057*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
3058*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(getRequiredImageAccess()),
3059*8975f5c5SAndroid Build Coastguard Worker ImageMipLevels::EnabledLevels));
3060*8975f5c5SAndroid Build Coastguard Worker }
3061*8975f5c5SAndroid Build Coastguard Worker
3062*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(performImageQueueTransferIfNecessary(contextVk));
3063*8975f5c5SAndroid Build Coastguard Worker
3064*8975f5c5SAndroid Build Coastguard Worker const bool hasRenderToTextureEXT =
3065*8975f5c5SAndroid Build Coastguard Worker contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled;
3066*8975f5c5SAndroid Build Coastguard Worker
3067*8975f5c5SAndroid Build Coastguard Worker // If samples > 1 here, we have a singlesampled texture that's being multisampled rendered to.
3068*8975f5c5SAndroid Build Coastguard Worker // In this case, create a multisampled image that is otherwise identical to the single sampled
3069*8975f5c5SAndroid Build Coastguard Worker // image. That multisampled image is used as color or depth/stencil attachment, while the
3070*8975f5c5SAndroid Build Coastguard Worker // original image is used as the resolve attachment.
3071*8975f5c5SAndroid Build Coastguard Worker const gl::RenderToTextureImageIndex renderToTextureIndex =
3072*8975f5c5SAndroid Build Coastguard Worker hasRenderToTextureEXT
3073*8975f5c5SAndroid Build Coastguard Worker ? gl::RenderToTextureImageIndex::Default
3074*8975f5c5SAndroid Build Coastguard Worker : static_cast<gl::RenderToTextureImageIndex>(PackSampleCount(samples));
3075*8975f5c5SAndroid Build Coastguard Worker
3076*8975f5c5SAndroid Build Coastguard Worker if (samples > 1 && !hasRenderToTextureEXT)
3077*8975f5c5SAndroid Build Coastguard Worker {
3078*8975f5c5SAndroid Build Coastguard Worker // Initialize mMultisampledImages and mMultisampledImageViews if necessary
3079*8975f5c5SAndroid Build Coastguard Worker if (mMultisampledImages == nullptr)
3080*8975f5c5SAndroid Build Coastguard Worker {
3081*8975f5c5SAndroid Build Coastguard Worker mMultisampledImages = std::make_unique<MultiSampleImages>();
3082*8975f5c5SAndroid Build Coastguard Worker mMultisampledImageViews = std::make_unique<MultiSampleImageViews>();
3083*8975f5c5SAndroid Build Coastguard Worker }
3084*8975f5c5SAndroid Build Coastguard Worker
3085*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.getBaseLevelDesc().samples <= 1);
3086*8975f5c5SAndroid Build Coastguard Worker
3087*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper &multisampledImage =
3088*8975f5c5SAndroid Build Coastguard Worker mMultisampledImages->at(renderToTextureIndex)[requestedLevel];
3089*8975f5c5SAndroid Build Coastguard Worker if (!multisampledImage.valid())
3090*8975f5c5SAndroid Build Coastguard Worker {
3091*8975f5c5SAndroid Build Coastguard Worker // Ensure the view serial is valid.
3092*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
3093*8975f5c5SAndroid Build Coastguard Worker mMultisampledImageViews->at(renderToTextureIndex)[requestedLevel].init(renderer);
3094*8975f5c5SAndroid Build Coastguard Worker
3095*8975f5c5SAndroid Build Coastguard Worker // The MSAA image always comes from the single sampled one, so disable robust init.
3096*8975f5c5SAndroid Build Coastguard Worker bool useRobustInit = false;
3097*8975f5c5SAndroid Build Coastguard Worker
3098*8975f5c5SAndroid Build Coastguard Worker // Calculate extents for multisample image
3099*8975f5c5SAndroid Build Coastguard Worker VkExtent3D extents = {};
3100*8975f5c5SAndroid Build Coastguard Worker gl_vk::GetExtent(
3101*8975f5c5SAndroid Build Coastguard Worker mImage->getLevelExtents(mImage->toVkLevel(gl::LevelIndex(requestedLevel))),
3102*8975f5c5SAndroid Build Coastguard Worker &extents);
3103*8975f5c5SAndroid Build Coastguard Worker
3104*8975f5c5SAndroid Build Coastguard Worker // Create the implicit multisampled image.
3105*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(multisampledImage.initImplicitMultisampledRenderToTexture(
3106*8975f5c5SAndroid Build Coastguard Worker contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
3107*8975f5c5SAndroid Build Coastguard Worker mState.getType(), samples, *mImage, extents, useRobustInit));
3108*8975f5c5SAndroid Build Coastguard Worker }
3109*8975f5c5SAndroid Build Coastguard Worker }
3110*8975f5c5SAndroid Build Coastguard Worker
3111*8975f5c5SAndroid Build Coastguard Worker GLuint layerIndex = 0, layerCount = 0, imageLayerCount = 0;
3112*8975f5c5SAndroid Build Coastguard Worker GetRenderTargetLayerCountAndIndex(mImage, imageIndex, &layerIndex, &layerCount,
3113*8975f5c5SAndroid Build Coastguard Worker &imageLayerCount);
3114*8975f5c5SAndroid Build Coastguard Worker
3115*8975f5c5SAndroid Build Coastguard Worker if (layerCount == 1)
3116*8975f5c5SAndroid Build Coastguard Worker {
3117*8975f5c5SAndroid Build Coastguard Worker initSingleLayerRenderTargets(contextVk, imageLayerCount, gl::LevelIndex(requestedLevel),
3118*8975f5c5SAndroid Build Coastguard Worker renderToTextureIndex);
3119*8975f5c5SAndroid Build Coastguard Worker
3120*8975f5c5SAndroid Build Coastguard Worker std::vector<RenderTargetVector> &levelRenderTargets =
3121*8975f5c5SAndroid Build Coastguard Worker mSingleLayerRenderTargets[renderToTextureIndex];
3122*8975f5c5SAndroid Build Coastguard Worker ASSERT(requestedLevel < static_cast<int32_t>(levelRenderTargets.size()));
3123*8975f5c5SAndroid Build Coastguard Worker
3124*8975f5c5SAndroid Build Coastguard Worker RenderTargetVector &layerRenderTargets = levelRenderTargets[requestedLevel];
3125*8975f5c5SAndroid Build Coastguard Worker ASSERT(imageIndex.getLayerIndex() < static_cast<int32_t>(layerRenderTargets.size()));
3126*8975f5c5SAndroid Build Coastguard Worker
3127*8975f5c5SAndroid Build Coastguard Worker *rtOut = &layerRenderTargets[layerIndex];
3128*8975f5c5SAndroid Build Coastguard Worker }
3129*8975f5c5SAndroid Build Coastguard Worker else
3130*8975f5c5SAndroid Build Coastguard Worker {
3131*8975f5c5SAndroid Build Coastguard Worker ASSERT(layerCount > 0);
3132*8975f5c5SAndroid Build Coastguard Worker *rtOut = getMultiLayerRenderTarget(contextVk, gl::LevelIndex(imageIndex.getLevelIndex()),
3133*8975f5c5SAndroid Build Coastguard Worker layerIndex, layerCount);
3134*8975f5c5SAndroid Build Coastguard Worker }
3135*8975f5c5SAndroid Build Coastguard Worker
3136*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3137*8975f5c5SAndroid Build Coastguard Worker }
3138*8975f5c5SAndroid Build Coastguard Worker
ensureImageInitialized(ContextVk * contextVk,ImageMipLevels mipLevels)3139*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels)
3140*8975f5c5SAndroid Build Coastguard Worker {
3141*8975f5c5SAndroid Build Coastguard Worker if (mImage->valid() && !mImage->hasStagedUpdatesInAllocatedLevels())
3142*8975f5c5SAndroid Build Coastguard Worker {
3143*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3144*8975f5c5SAndroid Build Coastguard Worker }
3145*8975f5c5SAndroid Build Coastguard Worker
3146*8975f5c5SAndroid Build Coastguard Worker if (!mImage->valid())
3147*8975f5c5SAndroid Build Coastguard Worker {
3148*8975f5c5SAndroid Build Coastguard Worker ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
3149*8975f5c5SAndroid Build Coastguard Worker
3150*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
3151*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
3152*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(getRequiredImageAccess()), mipLevels));
3153*8975f5c5SAndroid Build Coastguard Worker if (mipLevels == ImageMipLevels::FullMipChainForGenerateMipmap)
3154*8975f5c5SAndroid Build Coastguard Worker {
3155*8975f5c5SAndroid Build Coastguard Worker // Remove staged updates to non-base mips when generating mipmaps. These can only be
3156*8975f5c5SAndroid Build Coastguard Worker // emulated format init clears that are staged in initImage.
3157*8975f5c5SAndroid Build Coastguard Worker mImage->removeStagedUpdates(contextVk,
3158*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex(mState.getEffectiveBaseLevel() + 1),
3159*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex(mState.getMipmapMaxLevel()));
3160*8975f5c5SAndroid Build Coastguard Worker }
3161*8975f5c5SAndroid Build Coastguard Worker }
3162*8975f5c5SAndroid Build Coastguard Worker
3163*8975f5c5SAndroid Build Coastguard Worker return flushImageStagedUpdates(contextVk);
3164*8975f5c5SAndroid Build Coastguard Worker }
3165*8975f5c5SAndroid Build Coastguard Worker
flushImageStagedUpdates(ContextVk * contextVk)3166*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::flushImageStagedUpdates(ContextVk *contextVk)
3167*8975f5c5SAndroid Build Coastguard Worker {
3168*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->valid());
3169*8975f5c5SAndroid Build Coastguard Worker
3170*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex firstLevelGL = getNativeImageLevel(mImage->getFirstAllocatedLevel());
3171*8975f5c5SAndroid Build Coastguard Worker uint32_t firstLayer = getNativeImageLayer(0);
3172*8975f5c5SAndroid Build Coastguard Worker
3173*8975f5c5SAndroid Build Coastguard Worker return mImage->flushStagedUpdates(contextVk, firstLevelGL,
3174*8975f5c5SAndroid Build Coastguard Worker firstLevelGL + getImageViewLevelCount(), firstLayer,
3175*8975f5c5SAndroid Build Coastguard Worker firstLayer + getImageViewLayerCount(), mRedefinedLevels);
3176*8975f5c5SAndroid Build Coastguard Worker }
3177*8975f5c5SAndroid Build Coastguard Worker
performImageQueueTransferIfNecessary(ContextVk * contextVk)3178*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::performImageQueueTransferIfNecessary(ContextVk *contextVk)
3179*8975f5c5SAndroid Build Coastguard Worker {
3180*8975f5c5SAndroid Build Coastguard Worker if (mImage->valid() && mImage->isQueueFamilyChangeNeccesary(contextVk->getDeviceQueueIndex()))
3181*8975f5c5SAndroid Build Coastguard Worker {
3182*8975f5c5SAndroid Build Coastguard Worker vk::ImageLayout newLayout = vk::ImageLayout::AllGraphicsShadersWrite;
3183*8975f5c5SAndroid Build Coastguard Worker if (mImage->getUsage() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
3184*8975f5c5SAndroid Build Coastguard Worker {
3185*8975f5c5SAndroid Build Coastguard Worker newLayout = vk::ImageLayout::ColorWrite;
3186*8975f5c5SAndroid Build Coastguard Worker }
3187*8975f5c5SAndroid Build Coastguard Worker else if (mImage->getUsage() & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
3188*8975f5c5SAndroid Build Coastguard Worker {
3189*8975f5c5SAndroid Build Coastguard Worker newLayout = vk::ImageLayout::DepthWriteStencilWrite;
3190*8975f5c5SAndroid Build Coastguard Worker }
3191*8975f5c5SAndroid Build Coastguard Worker else if (mImage->getUsage() &
3192*8975f5c5SAndroid Build Coastguard Worker (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
3193*8975f5c5SAndroid Build Coastguard Worker {
3194*8975f5c5SAndroid Build Coastguard Worker newLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
3195*8975f5c5SAndroid Build Coastguard Worker }
3196*8975f5c5SAndroid Build Coastguard Worker
3197*8975f5c5SAndroid Build Coastguard Worker vk::OutsideRenderPassCommandBuffer *commandBuffer;
3198*8975f5c5SAndroid Build Coastguard Worker vk::CommandBufferAccess access;
3199*8975f5c5SAndroid Build Coastguard Worker access.onExternalAcquireRelease(mImage);
3200*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
3201*8975f5c5SAndroid Build Coastguard Worker mImage->changeLayoutAndQueue(contextVk, mImage->getAspectFlags(), newLayout,
3202*8975f5c5SAndroid Build Coastguard Worker contextVk->getDeviceQueueIndex(), commandBuffer);
3203*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->onEGLImageQueueChange());
3204*8975f5c5SAndroid Build Coastguard Worker }
3205*8975f5c5SAndroid Build Coastguard Worker
3206*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3207*8975f5c5SAndroid Build Coastguard Worker }
3208*8975f5c5SAndroid Build Coastguard Worker
initSingleLayerRenderTargets(ContextVk * contextVk,GLuint layerCount,gl::LevelIndex levelIndex,gl::RenderToTextureImageIndex renderToTextureIndex)3209*8975f5c5SAndroid Build Coastguard Worker void TextureVk::initSingleLayerRenderTargets(ContextVk *contextVk,
3210*8975f5c5SAndroid Build Coastguard Worker GLuint layerCount,
3211*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex levelIndex,
3212*8975f5c5SAndroid Build Coastguard Worker gl::RenderToTextureImageIndex renderToTextureIndex)
3213*8975f5c5SAndroid Build Coastguard Worker {
3214*8975f5c5SAndroid Build Coastguard Worker GLint requestedLevel = levelIndex.get();
3215*8975f5c5SAndroid Build Coastguard Worker std::vector<RenderTargetVector> &allLevelsRenderTargets =
3216*8975f5c5SAndroid Build Coastguard Worker mSingleLayerRenderTargets[renderToTextureIndex];
3217*8975f5c5SAndroid Build Coastguard Worker
3218*8975f5c5SAndroid Build Coastguard Worker if (allLevelsRenderTargets.size() <= static_cast<uint32_t>(requestedLevel))
3219*8975f5c5SAndroid Build Coastguard Worker {
3220*8975f5c5SAndroid Build Coastguard Worker allLevelsRenderTargets.resize(requestedLevel + 1);
3221*8975f5c5SAndroid Build Coastguard Worker }
3222*8975f5c5SAndroid Build Coastguard Worker
3223*8975f5c5SAndroid Build Coastguard Worker RenderTargetVector &renderTargets = allLevelsRenderTargets[requestedLevel];
3224*8975f5c5SAndroid Build Coastguard Worker
3225*8975f5c5SAndroid Build Coastguard Worker // Lazy init. Check if already initialized.
3226*8975f5c5SAndroid Build Coastguard Worker if (!renderTargets.empty())
3227*8975f5c5SAndroid Build Coastguard Worker {
3228*8975f5c5SAndroid Build Coastguard Worker return;
3229*8975f5c5SAndroid Build Coastguard Worker }
3230*8975f5c5SAndroid Build Coastguard Worker
3231*8975f5c5SAndroid Build Coastguard Worker // There are |layerCount| render targets, one for each layer
3232*8975f5c5SAndroid Build Coastguard Worker renderTargets.resize(layerCount);
3233*8975f5c5SAndroid Build Coastguard Worker
3234*8975f5c5SAndroid Build Coastguard Worker const bool isMultisampledRenderToTexture =
3235*8975f5c5SAndroid Build Coastguard Worker renderToTextureIndex != gl::RenderToTextureImageIndex::Default;
3236*8975f5c5SAndroid Build Coastguard Worker
3237*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *drawImage = mImage;
3238*8975f5c5SAndroid Build Coastguard Worker vk::ImageViewHelper *drawImageViews = &getImageViews();
3239*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper *resolveImage = nullptr;
3240*8975f5c5SAndroid Build Coastguard Worker vk::ImageViewHelper *resolveImageViews = nullptr;
3241*8975f5c5SAndroid Build Coastguard Worker
3242*8975f5c5SAndroid Build Coastguard Worker RenderTargetTransience transience = RenderTargetTransience::Default;
3243*8975f5c5SAndroid Build Coastguard Worker
3244*8975f5c5SAndroid Build Coastguard Worker // If multisampled render to texture, use the multisampled image as draw image instead, and
3245*8975f5c5SAndroid Build Coastguard Worker // resolve into the texture's image automatically.
3246*8975f5c5SAndroid Build Coastguard Worker if (isMultisampledRenderToTexture)
3247*8975f5c5SAndroid Build Coastguard Worker {
3248*8975f5c5SAndroid Build Coastguard Worker ASSERT(mMultisampledImages->at(renderToTextureIndex)[requestedLevel].valid());
3249*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mImage->isYuvResolve());
3250*8975f5c5SAndroid Build Coastguard Worker
3251*8975f5c5SAndroid Build Coastguard Worker resolveImage = drawImage;
3252*8975f5c5SAndroid Build Coastguard Worker resolveImageViews = drawImageViews;
3253*8975f5c5SAndroid Build Coastguard Worker drawImage = &mMultisampledImages->at(renderToTextureIndex)[requestedLevel];
3254*8975f5c5SAndroid Build Coastguard Worker drawImageViews = &mMultisampledImageViews->at(renderToTextureIndex)[requestedLevel];
3255*8975f5c5SAndroid Build Coastguard Worker
3256*8975f5c5SAndroid Build Coastguard Worker // If the texture is depth/stencil, GL_EXT_multisampled_render_to_texture2 explicitly
3257*8975f5c5SAndroid Build Coastguard Worker // indicates that there is no need for the image to be resolved. In that case, mark the
3258*8975f5c5SAndroid Build Coastguard Worker // render target as entirely transient.
3259*8975f5c5SAndroid Build Coastguard Worker if (mImage->getAspectFlags() != VK_IMAGE_ASPECT_COLOR_BIT)
3260*8975f5c5SAndroid Build Coastguard Worker {
3261*8975f5c5SAndroid Build Coastguard Worker transience = RenderTargetTransience::EntirelyTransient;
3262*8975f5c5SAndroid Build Coastguard Worker }
3263*8975f5c5SAndroid Build Coastguard Worker else
3264*8975f5c5SAndroid Build Coastguard Worker {
3265*8975f5c5SAndroid Build Coastguard Worker transience = RenderTargetTransience::MultisampledTransient;
3266*8975f5c5SAndroid Build Coastguard Worker }
3267*8975f5c5SAndroid Build Coastguard Worker }
3268*8975f5c5SAndroid Build Coastguard Worker else if (mImage->isYuvResolve())
3269*8975f5c5SAndroid Build Coastguard Worker {
3270*8975f5c5SAndroid Build Coastguard Worker // If rendering to YUV, similar to multisampled render to texture
3271*8975f5c5SAndroid Build Coastguard Worker resolveImage = drawImage;
3272*8975f5c5SAndroid Build Coastguard Worker resolveImageViews = drawImageViews;
3273*8975f5c5SAndroid Build Coastguard Worker
3274*8975f5c5SAndroid Build Coastguard Worker if (contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve())
3275*8975f5c5SAndroid Build Coastguard Worker {
3276*8975f5c5SAndroid Build Coastguard Worker // If null color attachment, we still keep drawImage as is (the same as
3277*8975f5c5SAndroid Build Coastguard Worker // resolveImage) to avoid special treatment in many places where they assume there must
3278*8975f5c5SAndroid Build Coastguard Worker // be a color attachment if there is a resolve attachment. But when renderPass is
3279*8975f5c5SAndroid Build Coastguard Worker // created, color attachment will be ignored.
3280*8975f5c5SAndroid Build Coastguard Worker }
3281*8975f5c5SAndroid Build Coastguard Worker else
3282*8975f5c5SAndroid Build Coastguard Worker {
3283*8975f5c5SAndroid Build Coastguard Worker transience = RenderTargetTransience::YuvResolveTransient;
3284*8975f5c5SAndroid Build Coastguard Worker // Need to populate drawImage here; either abuse mMultisampledImages etc
3285*8975f5c5SAndroid Build Coastguard Worker // or build something parallel to it. we don't have a vulkan implementation which
3286*8975f5c5SAndroid Build Coastguard Worker // wants this path yet, though.
3287*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
3288*8975f5c5SAndroid Build Coastguard Worker }
3289*8975f5c5SAndroid Build Coastguard Worker }
3290*8975f5c5SAndroid Build Coastguard Worker
3291*8975f5c5SAndroid Build Coastguard Worker for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
3292*8975f5c5SAndroid Build Coastguard Worker {
3293*8975f5c5SAndroid Build Coastguard Worker renderTargets[layerIndex].init(drawImage, drawImageViews, resolveImage, resolveImageViews,
3294*8975f5c5SAndroid Build Coastguard Worker mImageSiblingSerial, getNativeImageLevel(levelIndex),
3295*8975f5c5SAndroid Build Coastguard Worker getNativeImageLayer(layerIndex), 1, transience);
3296*8975f5c5SAndroid Build Coastguard Worker }
3297*8975f5c5SAndroid Build Coastguard Worker }
3298*8975f5c5SAndroid Build Coastguard Worker
getMultiLayerRenderTarget(ContextVk * contextVk,gl::LevelIndex level,GLuint layerIndex,GLuint layerCount)3299*8975f5c5SAndroid Build Coastguard Worker RenderTargetVk *TextureVk::getMultiLayerRenderTarget(ContextVk *contextVk,
3300*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex level,
3301*8975f5c5SAndroid Build Coastguard Worker GLuint layerIndex,
3302*8975f5c5SAndroid Build Coastguard Worker GLuint layerCount)
3303*8975f5c5SAndroid Build Coastguard Worker {
3304*8975f5c5SAndroid Build Coastguard Worker vk::ImageViewHelper *imageViews = &getImageViews();
3305*8975f5c5SAndroid Build Coastguard Worker vk::ImageSubresourceRange range = imageViews->getSubresourceDrawRange(
3306*8975f5c5SAndroid Build Coastguard Worker level, layerIndex, vk::GetLayerMode(*mImage, layerCount));
3307*8975f5c5SAndroid Build Coastguard Worker
3308*8975f5c5SAndroid Build Coastguard Worker auto iter = mMultiLayerRenderTargets.find(range);
3309*8975f5c5SAndroid Build Coastguard Worker if (iter != mMultiLayerRenderTargets.end())
3310*8975f5c5SAndroid Build Coastguard Worker {
3311*8975f5c5SAndroid Build Coastguard Worker return iter->second.get();
3312*8975f5c5SAndroid Build Coastguard Worker }
3313*8975f5c5SAndroid Build Coastguard Worker
3314*8975f5c5SAndroid Build Coastguard Worker // Create the layered render target. Note that multisampled render to texture is not
3315*8975f5c5SAndroid Build Coastguard Worker // allowed with layered render targets; nor is YUV rendering.
3316*8975f5c5SAndroid Build Coastguard Worker std::unique_ptr<RenderTargetVk> &rt = mMultiLayerRenderTargets[range];
3317*8975f5c5SAndroid Build Coastguard Worker if (!rt)
3318*8975f5c5SAndroid Build Coastguard Worker {
3319*8975f5c5SAndroid Build Coastguard Worker rt = std::make_unique<RenderTargetVk>();
3320*8975f5c5SAndroid Build Coastguard Worker }
3321*8975f5c5SAndroid Build Coastguard Worker
3322*8975f5c5SAndroid Build Coastguard Worker rt->init(mImage, imageViews, nullptr, nullptr, mImageSiblingSerial, getNativeImageLevel(level),
3323*8975f5c5SAndroid Build Coastguard Worker getNativeImageLayer(layerIndex), layerCount, RenderTargetTransience::Default);
3324*8975f5c5SAndroid Build Coastguard Worker
3325*8975f5c5SAndroid Build Coastguard Worker return rt.get();
3326*8975f5c5SAndroid Build Coastguard Worker }
3327*8975f5c5SAndroid Build Coastguard Worker
prepareForGenerateMipmap(ContextVk * contextVk)3328*8975f5c5SAndroid Build Coastguard Worker void TextureVk::prepareForGenerateMipmap(ContextVk *contextVk)
3329*8975f5c5SAndroid Build Coastguard Worker {
3330*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel());
3331*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex maxLevel(mState.getMipmapMaxLevel());
3332*8975f5c5SAndroid Build Coastguard Worker
3333*8975f5c5SAndroid Build Coastguard Worker // Remove staged updates to the range that's being respecified (which is all the mips except
3334*8975f5c5SAndroid Build Coastguard Worker // baseLevel).
3335*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex firstGeneratedLevel = baseLevel + 1;
3336*8975f5c5SAndroid Build Coastguard Worker mImage->removeStagedUpdates(contextVk, firstGeneratedLevel, maxLevel);
3337*8975f5c5SAndroid Build Coastguard Worker
3338*8975f5c5SAndroid Build Coastguard Worker TextureRedefineGenerateMipmapLevels(baseLevel, maxLevel, firstGeneratedLevel,
3339*8975f5c5SAndroid Build Coastguard Worker &mRedefinedLevels);
3340*8975f5c5SAndroid Build Coastguard Worker
3341*8975f5c5SAndroid Build Coastguard Worker // If generating mipmap and base level is incompatibly redefined, the image is going to be
3342*8975f5c5SAndroid Build Coastguard Worker // recreated. Don't try to preserve the other mips.
3343*8975f5c5SAndroid Build Coastguard Worker if (IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), baseLevel))
3344*8975f5c5SAndroid Build Coastguard Worker {
3345*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.getImmutableFormat());
3346*8975f5c5SAndroid Build Coastguard Worker releaseImage(contextVk);
3347*8975f5c5SAndroid Build Coastguard Worker }
3348*8975f5c5SAndroid Build Coastguard Worker
3349*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
3350*8975f5c5SAndroid Build Coastguard Worker VkImageType imageType = gl_vk::GetImageType(mState.getType());
3351*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
3352*8975f5c5SAndroid Build Coastguard Worker const GLint samples = baseLevelDesc.samples ? baseLevelDesc.samples : 1;
3353*8975f5c5SAndroid Build Coastguard Worker
3354*8975f5c5SAndroid Build Coastguard Worker // If the compute path is to be used to generate mipmaps, add the STORAGE usage.
3355*8975f5c5SAndroid Build Coastguard Worker if (CanGenerateMipmapWithCompute(contextVk->getRenderer(), imageType,
3356*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(getRequiredImageAccess()),
3357*8975f5c5SAndroid Build Coastguard Worker samples, mOwnsImage))
3358*8975f5c5SAndroid Build Coastguard Worker {
3359*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
3360*8975f5c5SAndroid Build Coastguard Worker }
3361*8975f5c5SAndroid Build Coastguard Worker }
3362*8975f5c5SAndroid Build Coastguard Worker
respecifyImageStorageIfNecessary(ContextVk * contextVk,gl::Command source)3363*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::respecifyImageStorageIfNecessary(ContextVk *contextVk, gl::Command source)
3364*8975f5c5SAndroid Build Coastguard Worker {
3365*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.getBuffer().get() == nullptr);
3366*8975f5c5SAndroid Build Coastguard Worker
3367*8975f5c5SAndroid Build Coastguard Worker VkImageUsageFlags oldUsageFlags = mImageUsageFlags;
3368*8975f5c5SAndroid Build Coastguard Worker VkImageCreateFlags oldCreateFlags = mImageCreateFlags;
3369*8975f5c5SAndroid Build Coastguard Worker
3370*8975f5c5SAndroid Build Coastguard Worker // Create a new image if the storage state is enabled for the first time.
3371*8975f5c5SAndroid Build Coastguard Worker if (mState.hasBeenBoundAsImage())
3372*8975f5c5SAndroid Build Coastguard Worker {
3373*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
3374*8975f5c5SAndroid Build Coastguard Worker mRequiresMutableStorage = true;
3375*8975f5c5SAndroid Build Coastguard Worker }
3376*8975f5c5SAndroid Build Coastguard Worker
3377*8975f5c5SAndroid Build Coastguard Worker // If we're handling dirty srgb decode/override state, we may have to reallocate the image with
3378*8975f5c5SAndroid Build Coastguard Worker // VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT. Vulkan requires this bit to be set in order to use
3379*8975f5c5SAndroid Build Coastguard Worker // imageviews with a format that does not match the texture's internal format.
3380*8975f5c5SAndroid Build Coastguard Worker if (isSRGBOverrideEnabled())
3381*8975f5c5SAndroid Build Coastguard Worker {
3382*8975f5c5SAndroid Build Coastguard Worker mRequiresMutableStorage = true;
3383*8975f5c5SAndroid Build Coastguard Worker }
3384*8975f5c5SAndroid Build Coastguard Worker
3385*8975f5c5SAndroid Build Coastguard Worker if (mRequiresMutableStorage)
3386*8975f5c5SAndroid Build Coastguard Worker {
3387*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
3388*8975f5c5SAndroid Build Coastguard Worker }
3389*8975f5c5SAndroid Build Coastguard Worker
3390*8975f5c5SAndroid Build Coastguard Worker // Create a new image if used as attachment for the first time. This must be called before
3391*8975f5c5SAndroid Build Coastguard Worker // prepareForGenerateMipmap since this changes the format which prepareForGenerateMipmap relies
3392*8975f5c5SAndroid Build Coastguard Worker // on.
3393*8975f5c5SAndroid Build Coastguard Worker if (mState.hasBeenBoundAsAttachment())
3394*8975f5c5SAndroid Build Coastguard Worker {
3395*8975f5c5SAndroid Build Coastguard Worker TextureUpdateResult updateResult = TextureUpdateResult::ImageUnaffected;
3396*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderable(contextVk, &updateResult));
3397*8975f5c5SAndroid Build Coastguard Worker if (updateResult == TextureUpdateResult::ImageRespecified)
3398*8975f5c5SAndroid Build Coastguard Worker {
3399*8975f5c5SAndroid Build Coastguard Worker oldUsageFlags = mImageUsageFlags;
3400*8975f5c5SAndroid Build Coastguard Worker oldCreateFlags = mImageCreateFlags;
3401*8975f5c5SAndroid Build Coastguard Worker }
3402*8975f5c5SAndroid Build Coastguard Worker }
3403*8975f5c5SAndroid Build Coastguard Worker
3404*8975f5c5SAndroid Build Coastguard Worker // Before redefining the image for any reason, check to see if it's about to go through mipmap
3405*8975f5c5SAndroid Build Coastguard Worker // generation. In that case, drop every staged change for the subsequent mips after base, and
3406*8975f5c5SAndroid Build Coastguard Worker // make sure the image is created with the complete mip chain.
3407*8975f5c5SAndroid Build Coastguard Worker const bool isGenerateMipmap = source == gl::Command::GenerateMipmap;
3408*8975f5c5SAndroid Build Coastguard Worker if (isGenerateMipmap)
3409*8975f5c5SAndroid Build Coastguard Worker {
3410*8975f5c5SAndroid Build Coastguard Worker prepareForGenerateMipmap(contextVk);
3411*8975f5c5SAndroid Build Coastguard Worker }
3412*8975f5c5SAndroid Build Coastguard Worker
3413*8975f5c5SAndroid Build Coastguard Worker // If texture was not originally created using the MSRTSS flag, it should be recreated when it
3414*8975f5c5SAndroid Build Coastguard Worker // is bound to an MSRTT framebuffer.
3415*8975f5c5SAndroid Build Coastguard Worker if (contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled &&
3416*8975f5c5SAndroid Build Coastguard Worker !contextVk->getFeatures().preferMSRTSSFlagByDefault.enabled &&
3417*8975f5c5SAndroid Build Coastguard Worker mState.hasBeenBoundToMSRTTFramebuffer() &&
3418*8975f5c5SAndroid Build Coastguard Worker ((mImageCreateFlags & VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) == 0))
3419*8975f5c5SAndroid Build Coastguard Worker {
3420*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(respecifyImageStorage(contextVk));
3421*8975f5c5SAndroid Build Coastguard Worker oldUsageFlags = mImageUsageFlags;
3422*8975f5c5SAndroid Build Coastguard Worker oldCreateFlags = mImageCreateFlags;
3423*8975f5c5SAndroid Build Coastguard Worker }
3424*8975f5c5SAndroid Build Coastguard Worker
3425*8975f5c5SAndroid Build Coastguard Worker // For immutable texture, base level does not affect allocation. Only usage flags are. If usage
3426*8975f5c5SAndroid Build Coastguard Worker // flag changed, we respecify image storage early on. This makes the code more reliable and also
3427*8975f5c5SAndroid Build Coastguard Worker // better performance wise. Otherwise, we will try to preserve base level by calling
3428*8975f5c5SAndroid Build Coastguard Worker // stageSelfAsSubresourceUpdates and then later on find out the mImageUsageFlags changed and the
3429*8975f5c5SAndroid Build Coastguard Worker // whole thing has to be respecified.
3430*8975f5c5SAndroid Build Coastguard Worker if (mState.getImmutableFormat() &&
3431*8975f5c5SAndroid Build Coastguard Worker (oldUsageFlags != mImageUsageFlags || oldCreateFlags != mImageCreateFlags))
3432*8975f5c5SAndroid Build Coastguard Worker {
3433*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(respecifyImageStorage(contextVk));
3434*8975f5c5SAndroid Build Coastguard Worker oldUsageFlags = mImageUsageFlags;
3435*8975f5c5SAndroid Build Coastguard Worker oldCreateFlags = mImageCreateFlags;
3436*8975f5c5SAndroid Build Coastguard Worker }
3437*8975f5c5SAndroid Build Coastguard Worker
3438*8975f5c5SAndroid Build Coastguard Worker // Set base and max level before initializing the image
3439*8975f5c5SAndroid Build Coastguard Worker TextureUpdateResult updateResult = TextureUpdateResult::ImageUnaffected;
3440*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(maybeUpdateBaseMaxLevels(contextVk, &updateResult));
3441*8975f5c5SAndroid Build Coastguard Worker
3442*8975f5c5SAndroid Build Coastguard Worker // Updating levels could have respecified the storage, recapture mImageCreateFlags
3443*8975f5c5SAndroid Build Coastguard Worker if (updateResult == TextureUpdateResult::ImageRespecified)
3444*8975f5c5SAndroid Build Coastguard Worker {
3445*8975f5c5SAndroid Build Coastguard Worker oldUsageFlags = mImageUsageFlags;
3446*8975f5c5SAndroid Build Coastguard Worker oldCreateFlags = mImageCreateFlags;
3447*8975f5c5SAndroid Build Coastguard Worker }
3448*8975f5c5SAndroid Build Coastguard Worker
3449*8975f5c5SAndroid Build Coastguard Worker // It is possible for the image to have a single level (because it doesn't use mipmapping),
3450*8975f5c5SAndroid Build Coastguard Worker // then have more levels defined in it and mipmapping enabled. In that case, the image needs
3451*8975f5c5SAndroid Build Coastguard Worker // to be recreated.
3452*8975f5c5SAndroid Build Coastguard Worker bool isMipmapEnabledByMinFilter = false;
3453*8975f5c5SAndroid Build Coastguard Worker if (!isGenerateMipmap && mImage && mImage->valid())
3454*8975f5c5SAndroid Build Coastguard Worker {
3455*8975f5c5SAndroid Build Coastguard Worker isMipmapEnabledByMinFilter =
3456*8975f5c5SAndroid Build Coastguard Worker mImage->getLevelCount() < getMipLevelCount(ImageMipLevels::EnabledLevels);
3457*8975f5c5SAndroid Build Coastguard Worker }
3458*8975f5c5SAndroid Build Coastguard Worker
3459*8975f5c5SAndroid Build Coastguard Worker // If generating mipmaps and the image needs to be recreated (not full-mip already, or changed
3460*8975f5c5SAndroid Build Coastguard Worker // usage flags), make sure it's recreated.
3461*8975f5c5SAndroid Build Coastguard Worker if (isGenerateMipmap && mImage && mImage->valid() &&
3462*8975f5c5SAndroid Build Coastguard Worker (oldUsageFlags != mImageUsageFlags ||
3463*8975f5c5SAndroid Build Coastguard Worker (!mState.getImmutableFormat() &&
3464*8975f5c5SAndroid Build Coastguard Worker mImage->getLevelCount() !=
3465*8975f5c5SAndroid Build Coastguard Worker getMipLevelCount(ImageMipLevels::FullMipChainForGenerateMipmap))))
3466*8975f5c5SAndroid Build Coastguard Worker {
3467*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOwnsImage);
3468*8975f5c5SAndroid Build Coastguard Worker // Immutable texture is not expected to reach here. The usage flag change should have
3469*8975f5c5SAndroid Build Coastguard Worker // been handled earlier and level count change should not need to reallocate
3470*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.getImmutableFormat());
3471*8975f5c5SAndroid Build Coastguard Worker
3472*8975f5c5SAndroid Build Coastguard Worker // Flush staged updates to the base level of the image. Note that updates to the rest of
3473*8975f5c5SAndroid Build Coastguard Worker // the levels have already been discarded through the |removeStagedUpdates| call above.
3474*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(flushImageStagedUpdates(contextVk));
3475*8975f5c5SAndroid Build Coastguard Worker
3476*8975f5c5SAndroid Build Coastguard Worker stageSelfAsSubresourceUpdates(contextVk);
3477*8975f5c5SAndroid Build Coastguard Worker
3478*8975f5c5SAndroid Build Coastguard Worker // Release the mImage without collecting garbage from image views.
3479*8975f5c5SAndroid Build Coastguard Worker releaseImage(contextVk);
3480*8975f5c5SAndroid Build Coastguard Worker }
3481*8975f5c5SAndroid Build Coastguard Worker
3482*8975f5c5SAndroid Build Coastguard Worker // Respecify the image if it's changed in usage, or if any of its levels are redefined and no
3483*8975f5c5SAndroid Build Coastguard Worker // update to base/max levels were done (otherwise the above call would have already taken care
3484*8975f5c5SAndroid Build Coastguard Worker // of this). Note that if both base/max and image usage are changed, the image is recreated
3485*8975f5c5SAndroid Build Coastguard Worker // twice, which incurs unnecessary copies. This is not expected to be happening in real
3486*8975f5c5SAndroid Build Coastguard Worker // applications.
3487*8975f5c5SAndroid Build Coastguard Worker if (oldUsageFlags != mImageUsageFlags || oldCreateFlags != mImageCreateFlags ||
3488*8975f5c5SAndroid Build Coastguard Worker TextureHasAnyRedefinedLevels(mRedefinedLevels) || isMipmapEnabledByMinFilter)
3489*8975f5c5SAndroid Build Coastguard Worker {
3490*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(respecifyImageStorage(contextVk));
3491*8975f5c5SAndroid Build Coastguard Worker }
3492*8975f5c5SAndroid Build Coastguard Worker
3493*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3494*8975f5c5SAndroid Build Coastguard Worker }
3495*8975f5c5SAndroid Build Coastguard Worker
onLabelUpdate(const gl::Context * context)3496*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::onLabelUpdate(const gl::Context *context)
3497*8975f5c5SAndroid Build Coastguard Worker {
3498*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
3499*8975f5c5SAndroid Build Coastguard Worker return updateTextureLabel(contextVk);
3500*8975f5c5SAndroid Build Coastguard Worker }
3501*8975f5c5SAndroid Build Coastguard Worker
updateTextureLabel(ContextVk * contextVk)3502*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::updateTextureLabel(ContextVk *contextVk)
3503*8975f5c5SAndroid Build Coastguard Worker {
3504*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
3505*8975f5c5SAndroid Build Coastguard Worker std::string label = mState.getLabel();
3506*8975f5c5SAndroid Build Coastguard Worker if (!label.empty() && renderer->enableDebugUtils() && imageValid())
3507*8975f5c5SAndroid Build Coastguard Worker {
3508*8975f5c5SAndroid Build Coastguard Worker return vk::SetDebugUtilsObjectName(contextVk, VK_OBJECT_TYPE_IMAGE,
3509*8975f5c5SAndroid Build Coastguard Worker (uint64_t)(getImage().getImage().getHandle()),
3510*8975f5c5SAndroid Build Coastguard Worker mState.getLabel());
3511*8975f5c5SAndroid Build Coastguard Worker }
3512*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3513*8975f5c5SAndroid Build Coastguard Worker }
3514*8975f5c5SAndroid Build Coastguard Worker
getRGBAConversionBufferHelper(vk::Renderer * renderer,angle::FormatID formatID) const3515*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper *TextureVk::getRGBAConversionBufferHelper(vk::Renderer *renderer,
3516*8975f5c5SAndroid Build Coastguard Worker angle::FormatID formatID) const
3517*8975f5c5SAndroid Build Coastguard Worker {
3518*8975f5c5SAndroid Build Coastguard Worker BufferVk *bufferVk = vk::GetImpl(getBuffer().get());
3519*8975f5c5SAndroid Build Coastguard Worker const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();
3520*8975f5c5SAndroid Build Coastguard Worker const VertexConversionBuffer::CacheKey cacheKey{
3521*8975f5c5SAndroid Build Coastguard Worker formatID, 16, static_cast<size_t>(bufferBinding.getOffset()), false, true};
3522*8975f5c5SAndroid Build Coastguard Worker ConversionBuffer *conversion = bufferVk->getVertexConversionBuffer(renderer, cacheKey);
3523*8975f5c5SAndroid Build Coastguard Worker return conversion->getBuffer();
3524*8975f5c5SAndroid Build Coastguard Worker }
3525*8975f5c5SAndroid Build Coastguard Worker
convertBufferToRGBA(ContextVk * contextVk,size_t & conversionBufferSize)3526*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::convertBufferToRGBA(ContextVk *contextVk, size_t &conversionBufferSize)
3527*8975f5c5SAndroid Build Coastguard Worker {
3528*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
3529*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
3530*8975f5c5SAndroid Build Coastguard Worker const vk::Format *imageUniformFormat =
3531*8975f5c5SAndroid Build Coastguard Worker &renderer->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
3532*8975f5c5SAndroid Build Coastguard Worker const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();
3533*8975f5c5SAndroid Build Coastguard Worker BufferVk *bufferVk = vk::GetImpl(getBuffer().get());
3534*8975f5c5SAndroid Build Coastguard Worker const size_t bindingOffset = bufferBinding.getOffset();
3535*8975f5c5SAndroid Build Coastguard Worker const VkDeviceSize bufferSize = bufferVk->getSize();
3536*8975f5c5SAndroid Build Coastguard Worker const VkDeviceSize bufferSizeFromOffset = bufferSize - bindingOffset;
3537*8975f5c5SAndroid Build Coastguard Worker conversionBufferSize = roundUpPow2<size_t>(static_cast<size_t>((bufferSizeFromOffset / 3) * 4),
3538*8975f5c5SAndroid Build Coastguard Worker 4 * sizeof(uint32_t));
3539*8975f5c5SAndroid Build Coastguard Worker
3540*8975f5c5SAndroid Build Coastguard Worker const VertexConversionBuffer::CacheKey cacheKey{imageUniformFormat->getIntendedFormatID(), 16,
3541*8975f5c5SAndroid Build Coastguard Worker bindingOffset, false, true};
3542*8975f5c5SAndroid Build Coastguard Worker ConversionBuffer *conversion = bufferVk->getVertexConversionBuffer(renderer, cacheKey);
3543*8975f5c5SAndroid Build Coastguard Worker mBufferContentsObservers->enableForBuffer(getBuffer().get());
3544*8975f5c5SAndroid Build Coastguard Worker if (!conversion->valid())
3545*8975f5c5SAndroid Build Coastguard Worker {
3546*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->initBufferForVertexConversion(conversion, conversionBufferSize,
3547*8975f5c5SAndroid Build Coastguard Worker vk::MemoryHostVisibility::NonVisible));
3548*8975f5c5SAndroid Build Coastguard Worker }
3549*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper *conversionBufferHelper = conversion->getBuffer();
3550*8975f5c5SAndroid Build Coastguard Worker
3551*8975f5c5SAndroid Build Coastguard Worker if (conversion->dirty())
3552*8975f5c5SAndroid Build Coastguard Worker {
3553*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
3554*8975f5c5SAndroid Build Coastguard Worker UtilsVk &utilsVk = contextVk->getUtils();
3555*8975f5c5SAndroid Build Coastguard Worker const VkDeviceSize pixelSize = 3 * sizeof(uint32_t);
3556*8975f5c5SAndroid Build Coastguard Worker const VkDeviceSize pixelCount = bufferSizeFromOffset / pixelSize;
3557*8975f5c5SAndroid Build Coastguard Worker
3558*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(utilsVk.copyRgbToRgba(contextVk, imageUniformFormat->getIntendedFormat(),
3559*8975f5c5SAndroid Build Coastguard Worker &bufferHelper, static_cast<uint32_t>(bindingOffset),
3560*8975f5c5SAndroid Build Coastguard Worker static_cast<uint32_t>(pixelCount), conversionBufferHelper));
3561*8975f5c5SAndroid Build Coastguard Worker conversion->clearDirty();
3562*8975f5c5SAndroid Build Coastguard Worker }
3563*8975f5c5SAndroid Build Coastguard Worker
3564*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3565*8975f5c5SAndroid Build Coastguard Worker }
3566*8975f5c5SAndroid Build Coastguard Worker
syncState(const gl::Context * context,const gl::Texture::DirtyBits & dirtyBits,gl::Command source)3567*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::syncState(const gl::Context *context,
3568*8975f5c5SAndroid Build Coastguard Worker const gl::Texture::DirtyBits &dirtyBits,
3569*8975f5c5SAndroid Build Coastguard Worker gl::Command source)
3570*8975f5c5SAndroid Build Coastguard Worker {
3571*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
3572*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
3573*8975f5c5SAndroid Build Coastguard Worker
3574*8975f5c5SAndroid Build Coastguard Worker // If this is a texture buffer, release buffer views. There's nothing else to sync. The
3575*8975f5c5SAndroid Build Coastguard Worker // image must already be deleted, and the sampler reset.
3576*8975f5c5SAndroid Build Coastguard Worker if (mState.getBuffer().get() != nullptr)
3577*8975f5c5SAndroid Build Coastguard Worker {
3578*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage == nullptr);
3579*8975f5c5SAndroid Build Coastguard Worker
3580*8975f5c5SAndroid Build Coastguard Worker const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();
3581*8975f5c5SAndroid Build Coastguard Worker
3582*8975f5c5SAndroid Build Coastguard Worker VkDeviceSize offset = bufferBinding.getOffset();
3583*8975f5c5SAndroid Build Coastguard Worker VkDeviceSize size = gl::GetBoundBufferAvailableSize(bufferBinding);
3584*8975f5c5SAndroid Build Coastguard Worker
3585*8975f5c5SAndroid Build Coastguard Worker if (NeedsRGBAEmulation(renderer, getBaseLevelFormat(renderer).getIntendedFormatID()))
3586*8975f5c5SAndroid Build Coastguard Worker {
3587*8975f5c5SAndroid Build Coastguard Worker size_t conversionBufferSize;
3588*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(convertBufferToRGBA(contextVk, conversionBufferSize));
3589*8975f5c5SAndroid Build Coastguard Worker offset = 0;
3590*8975f5c5SAndroid Build Coastguard Worker size = conversionBufferSize;
3591*8975f5c5SAndroid Build Coastguard Worker }
3592*8975f5c5SAndroid Build Coastguard Worker
3593*8975f5c5SAndroid Build Coastguard Worker mBufferViews.release(contextVk);
3594*8975f5c5SAndroid Build Coastguard Worker mBufferViews.init(renderer, offset, size);
3595*8975f5c5SAndroid Build Coastguard Worker mDescriptorSetCacheManager.releaseKeys(renderer);
3596*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3597*8975f5c5SAndroid Build Coastguard Worker }
3598*8975f5c5SAndroid Build Coastguard Worker
3599*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(respecifyImageStorageIfNecessary(contextVk, source));
3600*8975f5c5SAndroid Build Coastguard Worker
3601*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(performImageQueueTransferIfNecessary(contextVk));
3602*8975f5c5SAndroid Build Coastguard Worker
3603*8975f5c5SAndroid Build Coastguard Worker // Initialize the image storage and flush the pixel buffer.
3604*8975f5c5SAndroid Build Coastguard Worker const bool isGenerateMipmap = source == gl::Command::GenerateMipmap;
3605*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, isGenerateMipmap
3606*8975f5c5SAndroid Build Coastguard Worker ? ImageMipLevels::FullMipChainForGenerateMipmap
3607*8975f5c5SAndroid Build Coastguard Worker : ImageMipLevels::EnabledLevels));
3608*8975f5c5SAndroid Build Coastguard Worker
3609*8975f5c5SAndroid Build Coastguard Worker // Mask out the IMPLEMENTATION dirty bit to avoid unnecessary syncs.
3610*8975f5c5SAndroid Build Coastguard Worker // Keep it set when the border color is used and needs to be resynced.
3611*8975f5c5SAndroid Build Coastguard Worker gl::Texture::DirtyBits localBits = dirtyBits;
3612*8975f5c5SAndroid Build Coastguard Worker if (!mState.getSamplerState().usesBorderColor())
3613*8975f5c5SAndroid Build Coastguard Worker {
3614*8975f5c5SAndroid Build Coastguard Worker localBits.reset(gl::Texture::DIRTY_BIT_IMPLEMENTATION);
3615*8975f5c5SAndroid Build Coastguard Worker }
3616*8975f5c5SAndroid Build Coastguard Worker localBits.reset(gl::Texture::DIRTY_BIT_BASE_LEVEL);
3617*8975f5c5SAndroid Build Coastguard Worker localBits.reset(gl::Texture::DIRTY_BIT_MAX_LEVEL);
3618*8975f5c5SAndroid Build Coastguard Worker
3619*8975f5c5SAndroid Build Coastguard Worker // For AHBs, the ImageViews are created with VkSamplerYcbcrConversionInfo's chromaFilter
3620*8975f5c5SAndroid Build Coastguard Worker // matching min/magFilters as part of the eglEGLImageTargetTexture2DOES() call. However, the
3621*8975f5c5SAndroid Build Coastguard Worker // min/mag filters can change later, requiring the ImageViews to be refreshed.
3622*8975f5c5SAndroid Build Coastguard Worker if (mImage->valid() && mImage->hasImmutableSampler() &&
3623*8975f5c5SAndroid Build Coastguard Worker (dirtyBits.test(gl::Texture::DIRTY_BIT_MIN_FILTER) ||
3624*8975f5c5SAndroid Build Coastguard Worker dirtyBits.test(gl::Texture::DIRTY_BIT_MAG_FILTER)))
3625*8975f5c5SAndroid Build Coastguard Worker {
3626*8975f5c5SAndroid Build Coastguard Worker const gl::SamplerState &samplerState = mState.getSamplerState();
3627*8975f5c5SAndroid Build Coastguard Worker VkFilter chromaFilter = samplerState.getMinFilter() == samplerState.getMagFilter()
3628*8975f5c5SAndroid Build Coastguard Worker ? gl_vk::GetFilter(samplerState.getMinFilter())
3629*8975f5c5SAndroid Build Coastguard Worker : vk::kDefaultYCbCrChromaFilter;
3630*8975f5c5SAndroid Build Coastguard Worker if (mImage->updateChromaFilter(renderer, chromaFilter))
3631*8975f5c5SAndroid Build Coastguard Worker {
3632*8975f5c5SAndroid Build Coastguard Worker resetSampler();
3633*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(refreshImageViews(contextVk));
3634*8975f5c5SAndroid Build Coastguard Worker }
3635*8975f5c5SAndroid Build Coastguard Worker }
3636*8975f5c5SAndroid Build Coastguard Worker
3637*8975f5c5SAndroid Build Coastguard Worker if (localBits.none() && mSampler)
3638*8975f5c5SAndroid Build Coastguard Worker {
3639*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3640*8975f5c5SAndroid Build Coastguard Worker }
3641*8975f5c5SAndroid Build Coastguard Worker
3642*8975f5c5SAndroid Build Coastguard Worker if (mSampler)
3643*8975f5c5SAndroid Build Coastguard Worker {
3644*8975f5c5SAndroid Build Coastguard Worker resetSampler();
3645*8975f5c5SAndroid Build Coastguard Worker }
3646*8975f5c5SAndroid Build Coastguard Worker
3647*8975f5c5SAndroid Build Coastguard Worker if (localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_RED) ||
3648*8975f5c5SAndroid Build Coastguard Worker localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN) ||
3649*8975f5c5SAndroid Build Coastguard Worker localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE) ||
3650*8975f5c5SAndroid Build Coastguard Worker localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA))
3651*8975f5c5SAndroid Build Coastguard Worker {
3652*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(refreshImageViews(contextVk));
3653*8975f5c5SAndroid Build Coastguard Worker }
3654*8975f5c5SAndroid Build Coastguard Worker
3655*8975f5c5SAndroid Build Coastguard Worker if (localBits.test(gl::Texture::DIRTY_BIT_SRGB_OVERRIDE) ||
3656*8975f5c5SAndroid Build Coastguard Worker localBits.test(gl::Texture::DIRTY_BIT_SRGB_DECODE))
3657*8975f5c5SAndroid Build Coastguard Worker {
3658*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage != nullptr);
3659*8975f5c5SAndroid Build Coastguard Worker gl::SrgbDecode srgbDecode = (mState.getSamplerState().getSRGBDecode() == GL_SKIP_DECODE_EXT)
3660*8975f5c5SAndroid Build Coastguard Worker ? gl::SrgbDecode::Skip
3661*8975f5c5SAndroid Build Coastguard Worker : gl::SrgbDecode::Default;
3662*8975f5c5SAndroid Build Coastguard Worker mImageView.updateSrgbDecode(*mImage, srgbDecode);
3663*8975f5c5SAndroid Build Coastguard Worker mImageView.updateSrgbOverride(*mImage, mState.getSRGBOverride());
3664*8975f5c5SAndroid Build Coastguard Worker
3665*8975f5c5SAndroid Build Coastguard Worker if (!renderer->getFeatures().supportsImageFormatList.enabled)
3666*8975f5c5SAndroid Build Coastguard Worker {
3667*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(refreshImageViews(contextVk));
3668*8975f5c5SAndroid Build Coastguard Worker }
3669*8975f5c5SAndroid Build Coastguard Worker }
3670*8975f5c5SAndroid Build Coastguard Worker
3671*8975f5c5SAndroid Build Coastguard Worker vk::SamplerDesc samplerDesc(contextVk, mState.getSamplerState(), mState.isStencilMode(),
3672*8975f5c5SAndroid Build Coastguard Worker &mImage->getYcbcrConversionDesc(), mImage->getIntendedFormatID());
3673*8975f5c5SAndroid Build Coastguard Worker auto y2yConversionDesc = mImage->getY2YConversionDesc();
3674*8975f5c5SAndroid Build Coastguard Worker vk::SamplerDesc samplerDescSamplerExternal2DY2YEXT(contextVk, mState.getSamplerState(),
3675*8975f5c5SAndroid Build Coastguard Worker mState.isStencilMode(), &y2yConversionDesc,
3676*8975f5c5SAndroid Build Coastguard Worker mImage->getIntendedFormatID());
3677*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &mSampler));
3678*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDescSamplerExternal2DY2YEXT,
3679*8975f5c5SAndroid Build Coastguard Worker &mY2YSampler));
3680*8975f5c5SAndroid Build Coastguard Worker
3681*8975f5c5SAndroid Build Coastguard Worker updateCachedImageViewSerials();
3682*8975f5c5SAndroid Build Coastguard Worker
3683*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
3684*8975f5c5SAndroid Build Coastguard Worker }
3685*8975f5c5SAndroid Build Coastguard Worker
initializeContents(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex)3686*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::initializeContents(const gl::Context *context,
3687*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
3688*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex)
3689*8975f5c5SAndroid Build Coastguard Worker {
3690*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
3691*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &desc = mState.getImageDesc(imageIndex);
3692*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format =
3693*8975f5c5SAndroid Build Coastguard Worker contextVk->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);
3694*8975f5c5SAndroid Build Coastguard Worker
3695*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage);
3696*8975f5c5SAndroid Build Coastguard Worker // Note that we cannot ensure the image is initialized because we might be calling subImage
3697*8975f5c5SAndroid Build Coastguard Worker // on a non-complete cube map.
3698*8975f5c5SAndroid Build Coastguard Worker return mImage->stageRobustResourceClearWithFormat(
3699*8975f5c5SAndroid Build Coastguard Worker contextVk, imageIndex, desc.size, format.getIntendedFormat(),
3700*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormat(getRequiredImageAccess()));
3701*8975f5c5SAndroid Build Coastguard Worker }
3702*8975f5c5SAndroid Build Coastguard Worker
initializeContentsWithBlack(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex)3703*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::initializeContentsWithBlack(const gl::Context *context,
3704*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
3705*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex)
3706*8975f5c5SAndroid Build Coastguard Worker {
3707*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
3708*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &desc = mState.getImageDesc(imageIndex);
3709*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format =
3710*8975f5c5SAndroid Build Coastguard Worker contextVk->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);
3711*8975f5c5SAndroid Build Coastguard Worker
3712*8975f5c5SAndroid Build Coastguard Worker VkClearValue clearValue = {};
3713*8975f5c5SAndroid Build Coastguard Worker clearValue.color = {{0, 0, 0, 1.0f}};
3714*8975f5c5SAndroid Build Coastguard Worker
3715*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage);
3716*8975f5c5SAndroid Build Coastguard Worker // Note that we cannot ensure the image is initialized because we might be calling subImage
3717*8975f5c5SAndroid Build Coastguard Worker // on a non-complete cube map.
3718*8975f5c5SAndroid Build Coastguard Worker return mImage->stageResourceClearWithFormat(
3719*8975f5c5SAndroid Build Coastguard Worker contextVk, imageIndex, desc.size, format.getIntendedFormat(),
3720*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormat(getRequiredImageAccess()), clearValue);
3721*8975f5c5SAndroid Build Coastguard Worker }
3722*8975f5c5SAndroid Build Coastguard Worker
releaseOwnershipOfImage(const gl::Context * context)3723*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseOwnershipOfImage(const gl::Context *context)
3724*8975f5c5SAndroid Build Coastguard Worker {
3725*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
3726*8975f5c5SAndroid Build Coastguard Worker
3727*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mImageSiblingSerial.valid());
3728*8975f5c5SAndroid Build Coastguard Worker
3729*8975f5c5SAndroid Build Coastguard Worker mOwnsImage = false;
3730*8975f5c5SAndroid Build Coastguard Worker releaseAndDeleteImageAndViews(contextVk);
3731*8975f5c5SAndroid Build Coastguard Worker }
3732*8975f5c5SAndroid Build Coastguard Worker
getReadImageView(GLenum srgbDecode,bool texelFetchStaticUse,bool samplerExternal2DY2YEXT) const3733*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView &TextureVk::getReadImageView(GLenum srgbDecode,
3734*8975f5c5SAndroid Build Coastguard Worker bool texelFetchStaticUse,
3735*8975f5c5SAndroid Build Coastguard Worker bool samplerExternal2DY2YEXT) const
3736*8975f5c5SAndroid Build Coastguard Worker {
3737*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->valid());
3738*8975f5c5SAndroid Build Coastguard Worker
3739*8975f5c5SAndroid Build Coastguard Worker const vk::ImageViewHelper &imageViews = getImageViews();
3740*8975f5c5SAndroid Build Coastguard Worker
3741*8975f5c5SAndroid Build Coastguard Worker if (mState.isStencilMode() && imageViews.hasStencilReadImageView())
3742*8975f5c5SAndroid Build Coastguard Worker {
3743*8975f5c5SAndroid Build Coastguard Worker return imageViews.getStencilReadImageView();
3744*8975f5c5SAndroid Build Coastguard Worker }
3745*8975f5c5SAndroid Build Coastguard Worker
3746*8975f5c5SAndroid Build Coastguard Worker if (samplerExternal2DY2YEXT)
3747*8975f5c5SAndroid Build Coastguard Worker {
3748*8975f5c5SAndroid Build Coastguard Worker ASSERT(imageViews.getSamplerExternal2DY2YEXTImageView().valid());
3749*8975f5c5SAndroid Build Coastguard Worker return imageViews.getSamplerExternal2DY2YEXTImageView();
3750*8975f5c5SAndroid Build Coastguard Worker }
3751*8975f5c5SAndroid Build Coastguard Worker
3752*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage != nullptr && mImage->valid());
3753*8975f5c5SAndroid Build Coastguard Worker gl::SrgbDecode decode =
3754*8975f5c5SAndroid Build Coastguard Worker (srgbDecode == GL_DECODE_EXT) ? gl::SrgbDecode::Default : gl::SrgbDecode::Skip;
3755*8975f5c5SAndroid Build Coastguard Worker imageViews.updateSrgbDecode(*mImage, decode);
3756*8975f5c5SAndroid Build Coastguard Worker imageViews.updateStaticTexelFetch(*mImage, texelFetchStaticUse);
3757*8975f5c5SAndroid Build Coastguard Worker
3758*8975f5c5SAndroid Build Coastguard Worker ASSERT(imageViews.getReadImageView().valid());
3759*8975f5c5SAndroid Build Coastguard Worker return imageViews.getReadImageView();
3760*8975f5c5SAndroid Build Coastguard Worker }
3761*8975f5c5SAndroid Build Coastguard Worker
getCopyImageView() const3762*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView &TextureVk::getCopyImageView() const
3763*8975f5c5SAndroid Build Coastguard Worker {
3764*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage->valid());
3765*8975f5c5SAndroid Build Coastguard Worker
3766*8975f5c5SAndroid Build Coastguard Worker const vk::ImageViewHelper &imageViews = getImageViews();
3767*8975f5c5SAndroid Build Coastguard Worker
3768*8975f5c5SAndroid Build Coastguard Worker const angle::Format &angleFormat = mImage->getActualFormat();
3769*8975f5c5SAndroid Build Coastguard Worker ASSERT(angleFormat.isSRGB ==
3770*8975f5c5SAndroid Build Coastguard Worker (ConvertToLinear(mImage->getActualFormatID()) != angle::FormatID::NONE));
3771*8975f5c5SAndroid Build Coastguard Worker if (angleFormat.isSRGB)
3772*8975f5c5SAndroid Build Coastguard Worker {
3773*8975f5c5SAndroid Build Coastguard Worker return imageViews.getSRGBCopyImageView();
3774*8975f5c5SAndroid Build Coastguard Worker }
3775*8975f5c5SAndroid Build Coastguard Worker return imageViews.getLinearCopyImageView();
3776*8975f5c5SAndroid Build Coastguard Worker }
3777*8975f5c5SAndroid Build Coastguard Worker
getLevelLayerImageView(vk::Context * context,gl::LevelIndex level,size_t layer,const vk::ImageView ** imageViewOut)3778*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getLevelLayerImageView(vk::Context *context,
3779*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex level,
3780*8975f5c5SAndroid Build Coastguard Worker size_t layer,
3781*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView **imageViewOut)
3782*8975f5c5SAndroid Build Coastguard Worker {
3783*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage && mImage->valid());
3784*8975f5c5SAndroid Build Coastguard Worker
3785*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex levelGL = getNativeImageLevel(level);
3786*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex levelVk = mImage->toVkLevel(levelGL);
3787*8975f5c5SAndroid Build Coastguard Worker uint32_t nativeLayer = getNativeImageLayer(static_cast<uint32_t>(layer));
3788*8975f5c5SAndroid Build Coastguard Worker
3789*8975f5c5SAndroid Build Coastguard Worker return getImageViews().getLevelLayerDrawImageView(context, *mImage, levelVk, nativeLayer,
3790*8975f5c5SAndroid Build Coastguard Worker imageViewOut);
3791*8975f5c5SAndroid Build Coastguard Worker }
3792*8975f5c5SAndroid Build Coastguard Worker
getStorageImageView(vk::Context * context,const gl::ImageUnit & binding,const vk::ImageView ** imageViewOut)3793*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getStorageImageView(vk::Context *context,
3794*8975f5c5SAndroid Build Coastguard Worker const gl::ImageUnit &binding,
3795*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView **imageViewOut)
3796*8975f5c5SAndroid Build Coastguard Worker {
3797*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = context->getRenderer();
3798*8975f5c5SAndroid Build Coastguard Worker
3799*8975f5c5SAndroid Build Coastguard Worker angle::FormatID formatID = angle::Format::InternalFormatToID(binding.format);
3800*8975f5c5SAndroid Build Coastguard Worker const vk::Format *format = &renderer->getFormat(formatID);
3801*8975f5c5SAndroid Build Coastguard Worker
3802*8975f5c5SAndroid Build Coastguard Worker format = AdjustStorageViewFormatPerWorkarounds(renderer, format, getRequiredImageAccess());
3803*8975f5c5SAndroid Build Coastguard Worker
3804*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex nativeLevelGL =
3805*8975f5c5SAndroid Build Coastguard Worker getNativeImageLevel(gl::LevelIndex(static_cast<uint32_t>(binding.level)));
3806*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex nativeLevelVk = mImage->toVkLevel(nativeLevelGL);
3807*8975f5c5SAndroid Build Coastguard Worker
3808*8975f5c5SAndroid Build Coastguard Worker if (binding.layered != GL_TRUE)
3809*8975f5c5SAndroid Build Coastguard Worker {
3810*8975f5c5SAndroid Build Coastguard Worker uint32_t nativeLayer = getNativeImageLayer(static_cast<uint32_t>(binding.layer));
3811*8975f5c5SAndroid Build Coastguard Worker
3812*8975f5c5SAndroid Build Coastguard Worker return getImageViews().getLevelLayerStorageImageView(
3813*8975f5c5SAndroid Build Coastguard Worker context, *mImage, nativeLevelVk, nativeLayer,
3814*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
3815*8975f5c5SAndroid Build Coastguard Worker format->getActualImageFormatID(getRequiredImageAccess()), imageViewOut);
3816*8975f5c5SAndroid Build Coastguard Worker }
3817*8975f5c5SAndroid Build Coastguard Worker
3818*8975f5c5SAndroid Build Coastguard Worker uint32_t nativeLayer = getNativeImageLayer(0);
3819*8975f5c5SAndroid Build Coastguard Worker
3820*8975f5c5SAndroid Build Coastguard Worker return getImageViews().getLevelStorageImageView(
3821*8975f5c5SAndroid Build Coastguard Worker context, mState.getType(), *mImage, nativeLevelVk, nativeLayer,
3822*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
3823*8975f5c5SAndroid Build Coastguard Worker format->getActualImageFormatID(getRequiredImageAccess()), imageViewOut);
3824*8975f5c5SAndroid Build Coastguard Worker }
3825*8975f5c5SAndroid Build Coastguard Worker
getPossiblyEmulatedTextureBuffer(vk::Context * context) const3826*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper *TextureVk::getPossiblyEmulatedTextureBuffer(vk::Context *context) const
3827*8975f5c5SAndroid Build Coastguard Worker {
3828*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = context->getRenderer();
3829*8975f5c5SAndroid Build Coastguard Worker
3830*8975f5c5SAndroid Build Coastguard Worker angle::FormatID format = getBaseLevelFormat(renderer).getIntendedFormatID();
3831*8975f5c5SAndroid Build Coastguard Worker if (NeedsRGBAEmulation(renderer, format))
3832*8975f5c5SAndroid Build Coastguard Worker {
3833*8975f5c5SAndroid Build Coastguard Worker return getRGBAConversionBufferHelper(renderer, format);
3834*8975f5c5SAndroid Build Coastguard Worker }
3835*8975f5c5SAndroid Build Coastguard Worker
3836*8975f5c5SAndroid Build Coastguard Worker BufferVk *bufferVk = vk::GetImpl(getBuffer().get());
3837*8975f5c5SAndroid Build Coastguard Worker return &bufferVk->getBuffer();
3838*8975f5c5SAndroid Build Coastguard Worker }
3839*8975f5c5SAndroid Build Coastguard Worker
getBufferView(vk::Context * context,const vk::Format * imageUniformFormat,const gl::SamplerBinding * samplerBinding,bool isImage,const vk::BufferView ** viewOut)3840*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getBufferView(vk::Context *context,
3841*8975f5c5SAndroid Build Coastguard Worker const vk::Format *imageUniformFormat,
3842*8975f5c5SAndroid Build Coastguard Worker const gl::SamplerBinding *samplerBinding,
3843*8975f5c5SAndroid Build Coastguard Worker bool isImage,
3844*8975f5c5SAndroid Build Coastguard Worker const vk::BufferView **viewOut)
3845*8975f5c5SAndroid Build Coastguard Worker {
3846*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = context->getRenderer();
3847*8975f5c5SAndroid Build Coastguard Worker
3848*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.getBuffer().get() != nullptr);
3849*8975f5c5SAndroid Build Coastguard Worker
3850*8975f5c5SAndroid Build Coastguard Worker // Use the format specified by glTexBuffer if no format specified by the shader.
3851*8975f5c5SAndroid Build Coastguard Worker if (imageUniformFormat == nullptr)
3852*8975f5c5SAndroid Build Coastguard Worker {
3853*8975f5c5SAndroid Build Coastguard Worker imageUniformFormat = &getBaseLevelFormat(renderer);
3854*8975f5c5SAndroid Build Coastguard Worker }
3855*8975f5c5SAndroid Build Coastguard Worker
3856*8975f5c5SAndroid Build Coastguard Worker if (isImage)
3857*8975f5c5SAndroid Build Coastguard Worker {
3858*8975f5c5SAndroid Build Coastguard Worker imageUniformFormat = AdjustStorageViewFormatPerWorkarounds(renderer, imageUniformFormat,
3859*8975f5c5SAndroid Build Coastguard Worker getRequiredImageAccess());
3860*8975f5c5SAndroid Build Coastguard Worker }
3861*8975f5c5SAndroid Build Coastguard Worker
3862*8975f5c5SAndroid Build Coastguard Worker const vk::BufferHelper *buffer = &vk::GetImpl(mState.getBuffer().get())->getBuffer();
3863*8975f5c5SAndroid Build Coastguard Worker
3864*8975f5c5SAndroid Build Coastguard Worker if (NeedsRGBAEmulation(renderer, imageUniformFormat->getIntendedFormatID()))
3865*8975f5c5SAndroid Build Coastguard Worker {
3866*8975f5c5SAndroid Build Coastguard Worker buffer = getRGBAConversionBufferHelper(renderer, imageUniformFormat->getIntendedFormatID());
3867*8975f5c5SAndroid Build Coastguard Worker imageUniformFormat = &renderer->getFormat(
3868*8975f5c5SAndroid Build Coastguard Worker GetRGBAEmulationDstFormat(imageUniformFormat->getIntendedFormatID()));
3869*8975f5c5SAndroid Build Coastguard Worker }
3870*8975f5c5SAndroid Build Coastguard Worker
3871*8975f5c5SAndroid Build Coastguard Worker if (samplerBinding)
3872*8975f5c5SAndroid Build Coastguard Worker {
3873*8975f5c5SAndroid Build Coastguard Worker imageUniformFormat =
3874*8975f5c5SAndroid Build Coastguard Worker AdjustViewFormatForSampler(renderer, imageUniformFormat, samplerBinding->format);
3875*8975f5c5SAndroid Build Coastguard Worker }
3876*8975f5c5SAndroid Build Coastguard Worker
3877*8975f5c5SAndroid Build Coastguard Worker // Create a view for the required format.
3878*8975f5c5SAndroid Build Coastguard Worker return mBufferViews.getView(context, *buffer, buffer->getOffset(), *imageUniformFormat,
3879*8975f5c5SAndroid Build Coastguard Worker viewOut);
3880*8975f5c5SAndroid Build Coastguard Worker }
3881*8975f5c5SAndroid Build Coastguard Worker
initImage(ContextVk * contextVk,angle::FormatID intendedImageFormatID,angle::FormatID actualImageFormatID,ImageMipLevels mipLevels)3882*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::initImage(ContextVk *contextVk,
3883*8975f5c5SAndroid Build Coastguard Worker angle::FormatID intendedImageFormatID,
3884*8975f5c5SAndroid Build Coastguard Worker angle::FormatID actualImageFormatID,
3885*8975f5c5SAndroid Build Coastguard Worker ImageMipLevels mipLevels)
3886*8975f5c5SAndroid Build Coastguard Worker {
3887*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
3888*8975f5c5SAndroid Build Coastguard Worker
3889*8975f5c5SAndroid Build Coastguard Worker // Create the image. For immutable texture, we always allocate the full immutable levels
3890*8975f5c5SAndroid Build Coastguard Worker // specified by texStorage call. Otherwise we only try to allocate from base to max levels.
3891*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc *firstLevelDesc;
3892*8975f5c5SAndroid Build Coastguard Worker uint32_t firstLevel, levelCount;
3893*8975f5c5SAndroid Build Coastguard Worker if (mState.getImmutableFormat())
3894*8975f5c5SAndroid Build Coastguard Worker {
3895*8975f5c5SAndroid Build Coastguard Worker firstLevelDesc = &mState.getLevelZeroDesc();
3896*8975f5c5SAndroid Build Coastguard Worker firstLevel = 0;
3897*8975f5c5SAndroid Build Coastguard Worker levelCount = mState.getImmutableLevels();
3898*8975f5c5SAndroid Build Coastguard Worker }
3899*8975f5c5SAndroid Build Coastguard Worker else
3900*8975f5c5SAndroid Build Coastguard Worker {
3901*8975f5c5SAndroid Build Coastguard Worker firstLevelDesc = &mState.getBaseLevelDesc();
3902*8975f5c5SAndroid Build Coastguard Worker firstLevel = mState.getEffectiveBaseLevel();
3903*8975f5c5SAndroid Build Coastguard Worker levelCount = getMipLevelCount(mipLevels);
3904*8975f5c5SAndroid Build Coastguard Worker }
3905*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &firstLevelExtents = firstLevelDesc->size;
3906*8975f5c5SAndroid Build Coastguard Worker
3907*8975f5c5SAndroid Build Coastguard Worker VkExtent3D vkExtent;
3908*8975f5c5SAndroid Build Coastguard Worker uint32_t layerCount;
3909*8975f5c5SAndroid Build Coastguard Worker gl_vk::GetExtentsAndLayerCount(mState.getType(), firstLevelExtents, &vkExtent, &layerCount);
3910*8975f5c5SAndroid Build Coastguard Worker GLint samples = mState.getBaseLevelDesc().samples ? mState.getBaseLevelDesc().samples : 1;
3911*8975f5c5SAndroid Build Coastguard Worker
3912*8975f5c5SAndroid Build Coastguard Worker if (contextVk->getFeatures().limitSampleCountTo2.enabled)
3913*8975f5c5SAndroid Build Coastguard Worker {
3914*8975f5c5SAndroid Build Coastguard Worker samples = std::min(samples, 2);
3915*8975f5c5SAndroid Build Coastguard Worker }
3916*8975f5c5SAndroid Build Coastguard Worker
3917*8975f5c5SAndroid Build Coastguard Worker if (mState.hasProtectedContent())
3918*8975f5c5SAndroid Build Coastguard Worker {
3919*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags |= VK_IMAGE_CREATE_PROTECTED_BIT;
3920*8975f5c5SAndroid Build Coastguard Worker }
3921*8975f5c5SAndroid Build Coastguard Worker
3922*8975f5c5SAndroid Build Coastguard Worker if (renderer->getFeatures().supportsComputeTranscodeEtcToBc.enabled &&
3923*8975f5c5SAndroid Build Coastguard Worker IsETCFormat(intendedImageFormatID) && IsBCFormat(actualImageFormatID))
3924*8975f5c5SAndroid Build Coastguard Worker {
3925*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
3926*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_CREATE_EXTENDED_USAGE_BIT |
3927*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
3928*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
3929*8975f5c5SAndroid Build Coastguard Worker }
3930*8975f5c5SAndroid Build Coastguard Worker
3931*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags |=
3932*8975f5c5SAndroid Build Coastguard Worker vk::GetMinimalImageCreateFlags(renderer, mState.getType(), mImageUsageFlags);
3933*8975f5c5SAndroid Build Coastguard Worker
3934*8975f5c5SAndroid Build Coastguard Worker const VkFormat actualImageFormat =
3935*8975f5c5SAndroid Build Coastguard Worker rx::vk::GetVkFormatFromFormatID(renderer, actualImageFormatID);
3936*8975f5c5SAndroid Build Coastguard Worker const VkImageType imageType = gl_vk::GetImageType(mState.getType());
3937*8975f5c5SAndroid Build Coastguard Worker const VkImageTiling imageTiling = mImage->getTilingMode();
3938*8975f5c5SAndroid Build Coastguard Worker
3939*8975f5c5SAndroid Build Coastguard Worker // The MSRTSS bit is included in the create flag for all textures if the feature flag
3940*8975f5c5SAndroid Build Coastguard Worker // corresponding to its preference is enabled. Otherwise, it is enabled for a texture if it is
3941*8975f5c5SAndroid Build Coastguard Worker // bound to an MSRTT framebuffer.
3942*8975f5c5SAndroid Build Coastguard Worker const bool shouldIncludeMSRTSSBit =
3943*8975f5c5SAndroid Build Coastguard Worker contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled &&
3944*8975f5c5SAndroid Build Coastguard Worker (contextVk->getFeatures().preferMSRTSSFlagByDefault.enabled ||
3945*8975f5c5SAndroid Build Coastguard Worker mState.hasBeenBoundToMSRTTFramebuffer());
3946*8975f5c5SAndroid Build Coastguard Worker
3947*8975f5c5SAndroid Build Coastguard Worker if ((mImageUsageFlags & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
3948*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) != 0 &&
3949*8975f5c5SAndroid Build Coastguard Worker mOwnsImage && samples == 1 && shouldIncludeMSRTSSBit)
3950*8975f5c5SAndroid Build Coastguard Worker {
3951*8975f5c5SAndroid Build Coastguard Worker VkImageCreateFlags createFlagsMultisampled =
3952*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags | VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
3953*8975f5c5SAndroid Build Coastguard Worker bool isActualFormatSRGB = angle::Format::Get(actualImageFormatID).isSRGB;
3954*8975f5c5SAndroid Build Coastguard Worker const VkFormat additionalViewFormat = rx::vk::GetVkFormatFromFormatID(
3955*8975f5c5SAndroid Build Coastguard Worker renderer, isActualFormatSRGB ? ConvertToLinear(actualImageFormatID)
3956*8975f5c5SAndroid Build Coastguard Worker : ConvertToSRGB(actualImageFormatID));
3957*8975f5c5SAndroid Build Coastguard Worker const bool isAdditionalFormatValid = additionalViewFormat != VK_FORMAT_UNDEFINED;
3958*8975f5c5SAndroid Build Coastguard Worker
3959*8975f5c5SAndroid Build Coastguard Worker // If the texture has already been bound to an MSRTT framebuffer, lack of support should
3960*8975f5c5SAndroid Build Coastguard Worker // result in failure.
3961*8975f5c5SAndroid Build Coastguard Worker bool supportsMSRTTUsageActualFormat = vk::ImageHelper::FormatSupportsUsage(
3962*8975f5c5SAndroid Build Coastguard Worker renderer, actualImageFormat, imageType, imageTiling, mImageUsageFlags,
3963*8975f5c5SAndroid Build Coastguard Worker createFlagsMultisampled, nullptr, nullptr,
3964*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper::FormatSupportCheck::RequireMultisampling);
3965*8975f5c5SAndroid Build Coastguard Worker bool supportsMSRTTUsageAdditionalFormat =
3966*8975f5c5SAndroid Build Coastguard Worker !isAdditionalFormatValid ||
3967*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper::FormatSupportsUsage(
3968*8975f5c5SAndroid Build Coastguard Worker renderer, additionalViewFormat, imageType, imageTiling, mImageUsageFlags,
3969*8975f5c5SAndroid Build Coastguard Worker createFlagsMultisampled, nullptr, nullptr,
3970*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper::FormatSupportCheck::RequireMultisampling);
3971*8975f5c5SAndroid Build Coastguard Worker
3972*8975f5c5SAndroid Build Coastguard Worker bool supportsMSRTTUsage =
3973*8975f5c5SAndroid Build Coastguard Worker supportsMSRTTUsageActualFormat && supportsMSRTTUsageAdditionalFormat;
3974*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(mState.hasBeenBoundToMSRTTFramebuffer() && !supportsMSRTTUsage))
3975*8975f5c5SAndroid Build Coastguard Worker {
3976*8975f5c5SAndroid Build Coastguard Worker ERR() << "Texture bound to EXT_multisampled_render_to_texture framebuffer, "
3977*8975f5c5SAndroid Build Coastguard Worker << "but this device does not support this format.";
3978*8975f5c5SAndroid Build Coastguard Worker ANGLE_VK_TRY(contextVk, VK_ERROR_FORMAT_NOT_SUPPORTED);
3979*8975f5c5SAndroid Build Coastguard Worker }
3980*8975f5c5SAndroid Build Coastguard Worker
3981*8975f5c5SAndroid Build Coastguard Worker // Note: If we ever fail the following check, we should use the emulation path for this
3982*8975f5c5SAndroid Build Coastguard Worker // texture instead of ignoring MSRTT.
3983*8975f5c5SAndroid Build Coastguard Worker if (supportsMSRTTUsage)
3984*8975f5c5SAndroid Build Coastguard Worker {
3985*8975f5c5SAndroid Build Coastguard Worker // If supported by format add the MSRTSS flag because any texture might end up as an
3986*8975f5c5SAndroid Build Coastguard Worker // MSRTT attachment.
3987*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags |= VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
3988*8975f5c5SAndroid Build Coastguard Worker }
3989*8975f5c5SAndroid Build Coastguard Worker }
3990*8975f5c5SAndroid Build Coastguard Worker
3991*8975f5c5SAndroid Build Coastguard Worker // Any format with VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT support is required to also support
3992*8975f5c5SAndroid Build Coastguard Worker // VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT. So no format feature query is needed.
3993*8975f5c5SAndroid Build Coastguard Worker // However, it's still necessary to use vkGetPhysicalDeviceImageFormatProperties2 to ensure host
3994*8975f5c5SAndroid Build Coastguard Worker // image copy is supported for the specific usage and flags.
3995*8975f5c5SAndroid Build Coastguard Worker //
3996*8975f5c5SAndroid Build Coastguard Worker // All TextureVk images are expected to have VK_IMAGE_USAGE_SAMPLED_BIT, so that is not checked
3997*8975f5c5SAndroid Build Coastguard Worker // either.
3998*8975f5c5SAndroid Build Coastguard Worker ASSERT((mImageUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) != 0);
3999*8975f5c5SAndroid Build Coastguard Worker if (mOwnsImage && samples == 1 && renderer->getFeatures().supportsHostImageCopy.enabled)
4000*8975f5c5SAndroid Build Coastguard Worker {
4001*8975f5c5SAndroid Build Coastguard Worker VkHostImageCopyDevicePerformanceQueryEXT perfQuery = {};
4002*8975f5c5SAndroid Build Coastguard Worker perfQuery.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT;
4003*8975f5c5SAndroid Build Coastguard Worker
4004*8975f5c5SAndroid Build Coastguard Worker // If host image copy is supported at all ...
4005*8975f5c5SAndroid Build Coastguard Worker if (vk::ImageHelper::FormatSupportsUsage(
4006*8975f5c5SAndroid Build Coastguard Worker renderer, actualImageFormat, imageType, imageTiling,
4007*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags | VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT, mImageCreateFlags, nullptr,
4008*8975f5c5SAndroid Build Coastguard Worker &perfQuery, vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess))
4009*8975f5c5SAndroid Build Coastguard Worker {
4010*8975f5c5SAndroid Build Coastguard Worker // Only enable it if it has no performance impact whatsoever (or impact is tiny, given
4011*8975f5c5SAndroid Build Coastguard Worker // feature).
4012*8975f5c5SAndroid Build Coastguard Worker if (perfQuery.identicalMemoryLayout ||
4013*8975f5c5SAndroid Build Coastguard Worker (perfQuery.optimalDeviceAccess &&
4014*8975f5c5SAndroid Build Coastguard Worker renderer->getFeatures().allowHostImageCopyDespiteNonIdenticalLayout.enabled))
4015*8975f5c5SAndroid Build Coastguard Worker {
4016*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
4017*8975f5c5SAndroid Build Coastguard Worker }
4018*8975f5c5SAndroid Build Coastguard Worker }
4019*8975f5c5SAndroid Build Coastguard Worker }
4020*8975f5c5SAndroid Build Coastguard Worker
4021*8975f5c5SAndroid Build Coastguard Worker // Fixed rate compression
4022*8975f5c5SAndroid Build Coastguard Worker VkImageCompressionControlEXT *compressionInfo = nullptr;
4023*8975f5c5SAndroid Build Coastguard Worker VkImageCompressionControlEXT compressionInfoVar = {};
4024*8975f5c5SAndroid Build Coastguard Worker compressionInfoVar.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
4025*8975f5c5SAndroid Build Coastguard Worker VkImageCompressionFixedRateFlagsEXT compressionRates = VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT;
4026*8975f5c5SAndroid Build Coastguard Worker if (mOwnsImage && renderer->getFeatures().supportsImageCompressionControl.enabled)
4027*8975f5c5SAndroid Build Coastguard Worker {
4028*8975f5c5SAndroid Build Coastguard Worker // Use default compression control flag for query
4029*8975f5c5SAndroid Build Coastguard Worker compressionInfoVar.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
4030*8975f5c5SAndroid Build Coastguard Worker
4031*8975f5c5SAndroid Build Coastguard Worker VkImageCompressionPropertiesEXT compressionProp = {};
4032*8975f5c5SAndroid Build Coastguard Worker compressionProp.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;
4033*8975f5c5SAndroid Build Coastguard Worker
4034*8975f5c5SAndroid Build Coastguard Worker // If fixed rate compression is supported by this type, not support YUV now.
4035*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = renderer->getFormat(intendedImageFormatID);
4036*8975f5c5SAndroid Build Coastguard Worker if (!mImage->isYuvResolve() &&
4037*8975f5c5SAndroid Build Coastguard Worker (getFormatSupportedCompressionRatesImpl(renderer, format, 0, nullptr) != 0))
4038*8975f5c5SAndroid Build Coastguard Worker {
4039*8975f5c5SAndroid Build Coastguard Worker mImage->getCompressionFixedRate(&compressionInfoVar, &compressionRates,
4040*8975f5c5SAndroid Build Coastguard Worker mState.getSurfaceCompressionFixedRate());
4041*8975f5c5SAndroid Build Coastguard Worker compressionInfo = &compressionInfoVar;
4042*8975f5c5SAndroid Build Coastguard Worker }
4043*8975f5c5SAndroid Build Coastguard Worker }
4044*8975f5c5SAndroid Build Coastguard Worker
4045*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->initExternal(
4046*8975f5c5SAndroid Build Coastguard Worker contextVk, mState.getType(), vkExtent, intendedImageFormatID, actualImageFormatID, samples,
4047*8975f5c5SAndroid Build Coastguard Worker mImageUsageFlags, mImageCreateFlags, vk::ImageLayout::Undefined, nullptr,
4048*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex(firstLevel), levelCount, layerCount,
4049*8975f5c5SAndroid Build Coastguard Worker contextVk->isRobustResourceInitEnabled(), mState.hasProtectedContent(),
4050*8975f5c5SAndroid Build Coastguard Worker vk::ImageHelper::deriveConversionDesc(contextVk, actualImageFormatID,
4051*8975f5c5SAndroid Build Coastguard Worker intendedImageFormatID),
4052*8975f5c5SAndroid Build Coastguard Worker compressionInfo));
4053*8975f5c5SAndroid Build Coastguard Worker
4054*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(updateTextureLabel(contextVk));
4055*8975f5c5SAndroid Build Coastguard Worker
4056*8975f5c5SAndroid Build Coastguard Worker // Update create flags with mImage's create flags
4057*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags |= mImage->getCreateFlags();
4058*8975f5c5SAndroid Build Coastguard Worker mRequiresMutableStorage = (mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0;
4059*8975f5c5SAndroid Build Coastguard Worker
4060*8975f5c5SAndroid Build Coastguard Worker VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
4061*8975f5c5SAndroid Build Coastguard Worker if (mState.hasProtectedContent())
4062*8975f5c5SAndroid Build Coastguard Worker {
4063*8975f5c5SAndroid Build Coastguard Worker flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
4064*8975f5c5SAndroid Build Coastguard Worker }
4065*8975f5c5SAndroid Build Coastguard Worker
4066*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextVk->initImageAllocation(mImage, mState.hasProtectedContent(),
4067*8975f5c5SAndroid Build Coastguard Worker renderer->getMemoryProperties(), flags,
4068*8975f5c5SAndroid Build Coastguard Worker vk::MemoryAllocationType::TextureImage));
4069*8975f5c5SAndroid Build Coastguard Worker
4070*8975f5c5SAndroid Build Coastguard Worker const uint32_t viewLevelCount =
4071*8975f5c5SAndroid Build Coastguard Worker mState.getImmutableFormat() ? getMipLevelCount(ImageMipLevels::EnabledLevels) : levelCount;
4072*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImageViews(contextVk, viewLevelCount));
4073*8975f5c5SAndroid Build Coastguard Worker
4074*8975f5c5SAndroid Build Coastguard Worker mCurrentBaseLevel = gl::LevelIndex(mState.getBaseLevel());
4075*8975f5c5SAndroid Build Coastguard Worker mCurrentMaxLevel = gl::LevelIndex(mState.getMaxLevel());
4076*8975f5c5SAndroid Build Coastguard Worker
4077*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4078*8975f5c5SAndroid Build Coastguard Worker }
4079*8975f5c5SAndroid Build Coastguard Worker
initImageViews(ContextVk * contextVk,uint32_t levelCount)4080*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::initImageViews(ContextVk *contextVk, uint32_t levelCount)
4081*8975f5c5SAndroid Build Coastguard Worker {
4082*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImage != nullptr && mImage->valid());
4083*8975f5c5SAndroid Build Coastguard Worker
4084*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex baseLevelGL =
4085*8975f5c5SAndroid Build Coastguard Worker getNativeImageLevel(gl::LevelIndex(mState.getEffectiveBaseLevel()));
4086*8975f5c5SAndroid Build Coastguard Worker vk::LevelIndex baseLevelVk = mImage->toVkLevel(baseLevelGL);
4087*8975f5c5SAndroid Build Coastguard Worker uint32_t baseLayer = getNativeImageLayer(0);
4088*8975f5c5SAndroid Build Coastguard Worker
4089*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
4090*8975f5c5SAndroid Build Coastguard Worker const bool sized = baseLevelDesc.format.info->sized;
4091*8975f5c5SAndroid Build Coastguard Worker
4092*8975f5c5SAndroid Build Coastguard Worker const angle::Format &intendedFormat = mImage->getIntendedFormat();
4093*8975f5c5SAndroid Build Coastguard Worker gl::SwizzleState formatSwizzle = GetFormatSwizzle(intendedFormat, sized);
4094*8975f5c5SAndroid Build Coastguard Worker gl::SwizzleState readSwizzle = ApplySwizzle(formatSwizzle, mState.getSwizzleState());
4095*8975f5c5SAndroid Build Coastguard Worker
4096*8975f5c5SAndroid Build Coastguard Worker // Use this as a proxy for the SRGB override & skip decode settings.
4097*8975f5c5SAndroid Build Coastguard Worker bool createExtraSRGBViews = mRequiresMutableStorage;
4098*8975f5c5SAndroid Build Coastguard Worker
4099*8975f5c5SAndroid Build Coastguard Worker const VkImageUsageFlags kDisallowedSwizzledUsage =
4100*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
4101*8975f5c5SAndroid Build Coastguard Worker VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
4102*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getImageViews().initReadViews(contextVk, mState.getType(), *mImage, formatSwizzle,
4103*8975f5c5SAndroid Build Coastguard Worker readSwizzle, baseLevelVk, levelCount, baseLayer,
4104*8975f5c5SAndroid Build Coastguard Worker getImageViewLayerCount(), createExtraSRGBViews,
4105*8975f5c5SAndroid Build Coastguard Worker getImage().getUsage() & ~kDisallowedSwizzledUsage));
4106*8975f5c5SAndroid Build Coastguard Worker
4107*8975f5c5SAndroid Build Coastguard Worker updateCachedImageViewSerials();
4108*8975f5c5SAndroid Build Coastguard Worker
4109*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4110*8975f5c5SAndroid Build Coastguard Worker }
4111*8975f5c5SAndroid Build Coastguard Worker
releaseImage(ContextVk * contextVk)4112*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseImage(ContextVk *contextVk)
4113*8975f5c5SAndroid Build Coastguard Worker {
4114*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
4115*8975f5c5SAndroid Build Coastguard Worker
4116*8975f5c5SAndroid Build Coastguard Worker releaseImageViews(contextVk);
4117*8975f5c5SAndroid Build Coastguard Worker
4118*8975f5c5SAndroid Build Coastguard Worker if (mImage)
4119*8975f5c5SAndroid Build Coastguard Worker {
4120*8975f5c5SAndroid Build Coastguard Worker if (mOwnsImage)
4121*8975f5c5SAndroid Build Coastguard Worker {
4122*8975f5c5SAndroid Build Coastguard Worker mImage->releaseImageFromShareContexts(renderer, contextVk, mImageSiblingSerial);
4123*8975f5c5SAndroid Build Coastguard Worker }
4124*8975f5c5SAndroid Build Coastguard Worker else
4125*8975f5c5SAndroid Build Coastguard Worker {
4126*8975f5c5SAndroid Build Coastguard Worker mImage->finalizeImageLayoutInShareContexts(renderer, contextVk, mImageSiblingSerial);
4127*8975f5c5SAndroid Build Coastguard Worker mImageObserverBinding.bind(nullptr);
4128*8975f5c5SAndroid Build Coastguard Worker mImage = nullptr;
4129*8975f5c5SAndroid Build Coastguard Worker }
4130*8975f5c5SAndroid Build Coastguard Worker }
4131*8975f5c5SAndroid Build Coastguard Worker
4132*8975f5c5SAndroid Build Coastguard Worker if (mMultisampledImages)
4133*8975f5c5SAndroid Build Coastguard Worker {
4134*8975f5c5SAndroid Build Coastguard Worker for (gl::TexLevelArray<vk::ImageHelper> &images : *mMultisampledImages)
4135*8975f5c5SAndroid Build Coastguard Worker {
4136*8975f5c5SAndroid Build Coastguard Worker for (vk::ImageHelper &image : images)
4137*8975f5c5SAndroid Build Coastguard Worker {
4138*8975f5c5SAndroid Build Coastguard Worker if (image.valid())
4139*8975f5c5SAndroid Build Coastguard Worker {
4140*8975f5c5SAndroid Build Coastguard Worker image.releaseImageFromShareContexts(renderer, contextVk, mImageSiblingSerial);
4141*8975f5c5SAndroid Build Coastguard Worker }
4142*8975f5c5SAndroid Build Coastguard Worker }
4143*8975f5c5SAndroid Build Coastguard Worker }
4144*8975f5c5SAndroid Build Coastguard Worker mMultisampledImages.reset();
4145*8975f5c5SAndroid Build Coastguard Worker }
4146*8975f5c5SAndroid Build Coastguard Worker
4147*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectChanged);
4148*8975f5c5SAndroid Build Coastguard Worker mRedefinedLevels = {};
4149*8975f5c5SAndroid Build Coastguard Worker }
4150*8975f5c5SAndroid Build Coastguard Worker
releaseImageViews(ContextVk * contextVk)4151*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseImageViews(ContextVk *contextVk)
4152*8975f5c5SAndroid Build Coastguard Worker {
4153*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
4154*8975f5c5SAndroid Build Coastguard Worker
4155*8975f5c5SAndroid Build Coastguard Worker mDescriptorSetCacheManager.releaseKeys(renderer);
4156*8975f5c5SAndroid Build Coastguard Worker
4157*8975f5c5SAndroid Build Coastguard Worker if (mImage == nullptr)
4158*8975f5c5SAndroid Build Coastguard Worker {
4159*8975f5c5SAndroid Build Coastguard Worker if (mMultisampledImageViews)
4160*8975f5c5SAndroid Build Coastguard Worker {
4161*8975f5c5SAndroid Build Coastguard Worker for (gl::TexLevelArray<vk::ImageViewHelper> &imageViewHelpers :
4162*8975f5c5SAndroid Build Coastguard Worker *mMultisampledImageViews)
4163*8975f5c5SAndroid Build Coastguard Worker {
4164*8975f5c5SAndroid Build Coastguard Worker for (vk::ImageViewHelper &imageViewHelper : imageViewHelpers)
4165*8975f5c5SAndroid Build Coastguard Worker {
4166*8975f5c5SAndroid Build Coastguard Worker ASSERT(imageViewHelper.isImageViewGarbageEmpty());
4167*8975f5c5SAndroid Build Coastguard Worker }
4168*8975f5c5SAndroid Build Coastguard Worker }
4169*8975f5c5SAndroid Build Coastguard Worker mMultisampledImageViews.reset();
4170*8975f5c5SAndroid Build Coastguard Worker }
4171*8975f5c5SAndroid Build Coastguard Worker for (auto &renderTargets : mSingleLayerRenderTargets)
4172*8975f5c5SAndroid Build Coastguard Worker {
4173*8975f5c5SAndroid Build Coastguard Worker ASSERT(renderTargets.empty());
4174*8975f5c5SAndroid Build Coastguard Worker }
4175*8975f5c5SAndroid Build Coastguard Worker ASSERT(mMultiLayerRenderTargets.empty());
4176*8975f5c5SAndroid Build Coastguard Worker return;
4177*8975f5c5SAndroid Build Coastguard Worker }
4178*8975f5c5SAndroid Build Coastguard Worker
4179*8975f5c5SAndroid Build Coastguard Worker mImageView.release(renderer, mImage->getResourceUse());
4180*8975f5c5SAndroid Build Coastguard Worker
4181*8975f5c5SAndroid Build Coastguard Worker if (mMultisampledImageViews)
4182*8975f5c5SAndroid Build Coastguard Worker {
4183*8975f5c5SAndroid Build Coastguard Worker for (gl::TexLevelArray<vk::ImageViewHelper> &imageViewHelpers : *mMultisampledImageViews)
4184*8975f5c5SAndroid Build Coastguard Worker {
4185*8975f5c5SAndroid Build Coastguard Worker for (vk::ImageViewHelper &imageViewHelper : imageViewHelpers)
4186*8975f5c5SAndroid Build Coastguard Worker {
4187*8975f5c5SAndroid Build Coastguard Worker imageViewHelper.release(renderer, mImage->getResourceUse());
4188*8975f5c5SAndroid Build Coastguard Worker }
4189*8975f5c5SAndroid Build Coastguard Worker }
4190*8975f5c5SAndroid Build Coastguard Worker mMultisampledImageViews.reset();
4191*8975f5c5SAndroid Build Coastguard Worker }
4192*8975f5c5SAndroid Build Coastguard Worker
4193*8975f5c5SAndroid Build Coastguard Worker for (auto &renderTargets : mSingleLayerRenderTargets)
4194*8975f5c5SAndroid Build Coastguard Worker {
4195*8975f5c5SAndroid Build Coastguard Worker for (RenderTargetVector &renderTargetLevels : renderTargets)
4196*8975f5c5SAndroid Build Coastguard Worker {
4197*8975f5c5SAndroid Build Coastguard Worker for (RenderTargetVk &renderTargetVk : renderTargetLevels)
4198*8975f5c5SAndroid Build Coastguard Worker {
4199*8975f5c5SAndroid Build Coastguard Worker renderTargetVk.releaseFramebuffers(contextVk);
4200*8975f5c5SAndroid Build Coastguard Worker }
4201*8975f5c5SAndroid Build Coastguard Worker // Clear the layers tracked for each level
4202*8975f5c5SAndroid Build Coastguard Worker renderTargetLevels.clear();
4203*8975f5c5SAndroid Build Coastguard Worker }
4204*8975f5c5SAndroid Build Coastguard Worker // Then clear the levels
4205*8975f5c5SAndroid Build Coastguard Worker renderTargets.clear();
4206*8975f5c5SAndroid Build Coastguard Worker }
4207*8975f5c5SAndroid Build Coastguard Worker
4208*8975f5c5SAndroid Build Coastguard Worker for (auto &renderTargetPair : mMultiLayerRenderTargets)
4209*8975f5c5SAndroid Build Coastguard Worker {
4210*8975f5c5SAndroid Build Coastguard Worker renderTargetPair.second->releaseFramebuffers(contextVk);
4211*8975f5c5SAndroid Build Coastguard Worker }
4212*8975f5c5SAndroid Build Coastguard Worker mMultiLayerRenderTargets.clear();
4213*8975f5c5SAndroid Build Coastguard Worker }
4214*8975f5c5SAndroid Build Coastguard Worker
releaseStagedUpdates(ContextVk * contextVk)4215*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseStagedUpdates(ContextVk *contextVk)
4216*8975f5c5SAndroid Build Coastguard Worker {
4217*8975f5c5SAndroid Build Coastguard Worker if (mImage)
4218*8975f5c5SAndroid Build Coastguard Worker {
4219*8975f5c5SAndroid Build Coastguard Worker mImage->releaseStagedUpdates(contextVk->getRenderer());
4220*8975f5c5SAndroid Build Coastguard Worker }
4221*8975f5c5SAndroid Build Coastguard Worker }
4222*8975f5c5SAndroid Build Coastguard Worker
getMipLevelCount(ImageMipLevels mipLevels) const4223*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getMipLevelCount(ImageMipLevels mipLevels) const
4224*8975f5c5SAndroid Build Coastguard Worker {
4225*8975f5c5SAndroid Build Coastguard Worker switch (mipLevels)
4226*8975f5c5SAndroid Build Coastguard Worker {
4227*8975f5c5SAndroid Build Coastguard Worker // Returns level count from base to max that has been specified, i.e, enabled.
4228*8975f5c5SAndroid Build Coastguard Worker case ImageMipLevels::EnabledLevels:
4229*8975f5c5SAndroid Build Coastguard Worker return mState.getEnabledLevelCount();
4230*8975f5c5SAndroid Build Coastguard Worker // Returns all mipmap levels from base to max regardless if an image has been specified or
4231*8975f5c5SAndroid Build Coastguard Worker // not.
4232*8975f5c5SAndroid Build Coastguard Worker case ImageMipLevels::FullMipChainForGenerateMipmap:
4233*8975f5c5SAndroid Build Coastguard Worker return getMaxLevelCount() - mState.getEffectiveBaseLevel();
4234*8975f5c5SAndroid Build Coastguard Worker
4235*8975f5c5SAndroid Build Coastguard Worker default:
4236*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
4237*8975f5c5SAndroid Build Coastguard Worker return 0;
4238*8975f5c5SAndroid Build Coastguard Worker }
4239*8975f5c5SAndroid Build Coastguard Worker }
4240*8975f5c5SAndroid Build Coastguard Worker
getMaxLevelCount() const4241*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getMaxLevelCount() const
4242*8975f5c5SAndroid Build Coastguard Worker {
4243*8975f5c5SAndroid Build Coastguard Worker // getMipmapMaxLevel will be 0 here if mipmaps are not used, so the levelCount is always +1.
4244*8975f5c5SAndroid Build Coastguard Worker return mState.getMipmapMaxLevel() + 1;
4245*8975f5c5SAndroid Build Coastguard Worker }
4246*8975f5c5SAndroid Build Coastguard Worker
generateMipmapLevelsWithCPU(ContextVk * contextVk,const angle::Format & sourceFormat,GLuint layer,gl::LevelIndex firstMipLevel,gl::LevelIndex maxMipLevel,const size_t sourceWidth,const size_t sourceHeight,const size_t sourceDepth,const size_t sourceRowPitch,const size_t sourceDepthPitch,uint8_t * sourceData)4247*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
4248*8975f5c5SAndroid Build Coastguard Worker const angle::Format &sourceFormat,
4249*8975f5c5SAndroid Build Coastguard Worker GLuint layer,
4250*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex firstMipLevel,
4251*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex maxMipLevel,
4252*8975f5c5SAndroid Build Coastguard Worker const size_t sourceWidth,
4253*8975f5c5SAndroid Build Coastguard Worker const size_t sourceHeight,
4254*8975f5c5SAndroid Build Coastguard Worker const size_t sourceDepth,
4255*8975f5c5SAndroid Build Coastguard Worker const size_t sourceRowPitch,
4256*8975f5c5SAndroid Build Coastguard Worker const size_t sourceDepthPitch,
4257*8975f5c5SAndroid Build Coastguard Worker uint8_t *sourceData)
4258*8975f5c5SAndroid Build Coastguard Worker {
4259*8975f5c5SAndroid Build Coastguard Worker size_t previousLevelWidth = sourceWidth;
4260*8975f5c5SAndroid Build Coastguard Worker size_t previousLevelHeight = sourceHeight;
4261*8975f5c5SAndroid Build Coastguard Worker size_t previousLevelDepth = sourceDepth;
4262*8975f5c5SAndroid Build Coastguard Worker uint8_t *previousLevelData = sourceData;
4263*8975f5c5SAndroid Build Coastguard Worker size_t previousLevelRowPitch = sourceRowPitch;
4264*8975f5c5SAndroid Build Coastguard Worker size_t previousLevelDepthPitch = sourceDepthPitch;
4265*8975f5c5SAndroid Build Coastguard Worker
4266*8975f5c5SAndroid Build Coastguard Worker for (gl::LevelIndex currentMipLevel = firstMipLevel; currentMipLevel <= maxMipLevel;
4267*8975f5c5SAndroid Build Coastguard Worker ++currentMipLevel)
4268*8975f5c5SAndroid Build Coastguard Worker {
4269*8975f5c5SAndroid Build Coastguard Worker // Compute next level width and height.
4270*8975f5c5SAndroid Build Coastguard Worker size_t mipWidth = std::max<size_t>(1, previousLevelWidth >> 1);
4271*8975f5c5SAndroid Build Coastguard Worker size_t mipHeight = std::max<size_t>(1, previousLevelHeight >> 1);
4272*8975f5c5SAndroid Build Coastguard Worker size_t mipDepth = std::max<size_t>(1, previousLevelDepth >> 1);
4273*8975f5c5SAndroid Build Coastguard Worker
4274*8975f5c5SAndroid Build Coastguard Worker // With the width and height of the next mip, we can allocate the next buffer we need.
4275*8975f5c5SAndroid Build Coastguard Worker uint8_t *destData = nullptr;
4276*8975f5c5SAndroid Build Coastguard Worker size_t destRowPitch = mipWidth * sourceFormat.pixelBytes;
4277*8975f5c5SAndroid Build Coastguard Worker size_t destDepthPitch = destRowPitch * mipHeight;
4278*8975f5c5SAndroid Build Coastguard Worker
4279*8975f5c5SAndroid Build Coastguard Worker size_t mipAllocationSize = destDepthPitch * mipDepth;
4280*8975f5c5SAndroid Build Coastguard Worker gl::Extents mipLevelExtents(static_cast<int>(mipWidth), static_cast<int>(mipHeight),
4281*8975f5c5SAndroid Build Coastguard Worker static_cast<int>(mipDepth));
4282*8975f5c5SAndroid Build Coastguard Worker
4283*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
4284*8975f5c5SAndroid Build Coastguard Worker contextVk, mipAllocationSize,
4285*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel.get(), layer),
4286*8975f5c5SAndroid Build Coastguard Worker mipLevelExtents, gl::Offset(), &destData, sourceFormat.id));
4287*8975f5c5SAndroid Build Coastguard Worker
4288*8975f5c5SAndroid Build Coastguard Worker // Generate the mipmap into that new buffer
4289*8975f5c5SAndroid Build Coastguard Worker sourceFormat.mipGenerationFunction(
4290*8975f5c5SAndroid Build Coastguard Worker previousLevelWidth, previousLevelHeight, previousLevelDepth, previousLevelData,
4291*8975f5c5SAndroid Build Coastguard Worker previousLevelRowPitch, previousLevelDepthPitch, destData, destRowPitch, destDepthPitch);
4292*8975f5c5SAndroid Build Coastguard Worker
4293*8975f5c5SAndroid Build Coastguard Worker // Swap for the next iteration
4294*8975f5c5SAndroid Build Coastguard Worker previousLevelWidth = mipWidth;
4295*8975f5c5SAndroid Build Coastguard Worker previousLevelHeight = mipHeight;
4296*8975f5c5SAndroid Build Coastguard Worker previousLevelDepth = mipDepth;
4297*8975f5c5SAndroid Build Coastguard Worker previousLevelData = destData;
4298*8975f5c5SAndroid Build Coastguard Worker previousLevelRowPitch = destRowPitch;
4299*8975f5c5SAndroid Build Coastguard Worker previousLevelDepthPitch = destDepthPitch;
4300*8975f5c5SAndroid Build Coastguard Worker }
4301*8975f5c5SAndroid Build Coastguard Worker
4302*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4303*8975f5c5SAndroid Build Coastguard Worker }
4304*8975f5c5SAndroid Build Coastguard Worker
getImplementationSizedFormat(const gl::Context * context) const4305*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &TextureVk::getImplementationSizedFormat(const gl::Context *context) const
4306*8975f5c5SAndroid Build Coastguard Worker {
4307*8975f5c5SAndroid Build Coastguard Worker GLenum sizedFormat = GL_NONE;
4308*8975f5c5SAndroid Build Coastguard Worker
4309*8975f5c5SAndroid Build Coastguard Worker if (mImage && mImage->valid())
4310*8975f5c5SAndroid Build Coastguard Worker {
4311*8975f5c5SAndroid Build Coastguard Worker sizedFormat = mImage->getActualFormat().glInternalFormat;
4312*8975f5c5SAndroid Build Coastguard Worker }
4313*8975f5c5SAndroid Build Coastguard Worker else
4314*8975f5c5SAndroid Build Coastguard Worker {
4315*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
4316*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
4317*8975f5c5SAndroid Build Coastguard Worker sizedFormat = format.getActualImageFormat(getRequiredImageAccess()).glInternalFormat;
4318*8975f5c5SAndroid Build Coastguard Worker }
4319*8975f5c5SAndroid Build Coastguard Worker
4320*8975f5c5SAndroid Build Coastguard Worker return gl::GetSizedInternalFormatInfo(sizedFormat);
4321*8975f5c5SAndroid Build Coastguard Worker }
4322*8975f5c5SAndroid Build Coastguard Worker
getColorReadFormat(const gl::Context * context)4323*8975f5c5SAndroid Build Coastguard Worker GLenum TextureVk::getColorReadFormat(const gl::Context *context)
4324*8975f5c5SAndroid Build Coastguard Worker {
4325*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &sizedFormat = getImplementationSizedFormat(context);
4326*8975f5c5SAndroid Build Coastguard Worker return sizedFormat.format;
4327*8975f5c5SAndroid Build Coastguard Worker }
4328*8975f5c5SAndroid Build Coastguard Worker
getColorReadType(const gl::Context * context)4329*8975f5c5SAndroid Build Coastguard Worker GLenum TextureVk::getColorReadType(const gl::Context *context)
4330*8975f5c5SAndroid Build Coastguard Worker {
4331*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &sizedFormat = getImplementationSizedFormat(context);
4332*8975f5c5SAndroid Build Coastguard Worker return sizedFormat.type;
4333*8975f5c5SAndroid Build Coastguard Worker }
4334*8975f5c5SAndroid Build Coastguard Worker
getTexImage(const gl::Context * context,const gl::PixelPackState & packState,gl::Buffer * packBuffer,gl::TextureTarget target,GLint level,GLenum format,GLenum type,void * pixels)4335*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getTexImage(const gl::Context *context,
4336*8975f5c5SAndroid Build Coastguard Worker const gl::PixelPackState &packState,
4337*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *packBuffer,
4338*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget target,
4339*8975f5c5SAndroid Build Coastguard Worker GLint level,
4340*8975f5c5SAndroid Build Coastguard Worker GLenum format,
4341*8975f5c5SAndroid Build Coastguard Worker GLenum type,
4342*8975f5c5SAndroid Build Coastguard Worker void *pixels)
4343*8975f5c5SAndroid Build Coastguard Worker {
4344*8975f5c5SAndroid Build Coastguard Worker if (packBuffer && this->isCompressedFormatEmulated(context, target, level))
4345*8975f5c5SAndroid Build Coastguard Worker {
4346*8975f5c5SAndroid Build Coastguard Worker // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
4347*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
4348*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop;
4349*8975f5c5SAndroid Build Coastguard Worker }
4350*8975f5c5SAndroid Build Coastguard Worker
4351*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
4352*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
4353*8975f5c5SAndroid Build Coastguard Worker
4354*8975f5c5SAndroid Build Coastguard Worker GLint baseLevel = static_cast<int>(mState.getBaseLevel());
4355*8975f5c5SAndroid Build Coastguard Worker if (level < baseLevel || level >= baseLevel + static_cast<int>(mState.getEnabledLevelCount()))
4356*8975f5c5SAndroid Build Coastguard Worker {
4357*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42264855): Handle inconsistent textures.
4358*8975f5c5SAndroid Build Coastguard Worker WARN() << "GetTexImage for inconsistent texture levels is not implemented.";
4359*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
4360*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4361*8975f5c5SAndroid Build Coastguard Worker }
4362*8975f5c5SAndroid Build Coastguard Worker
4363*8975f5c5SAndroid Build Coastguard Worker gl::MaybeOverrideLuminance(format, type, getColorReadFormat(context),
4364*8975f5c5SAndroid Build Coastguard Worker getColorReadType(context));
4365*8975f5c5SAndroid Build Coastguard Worker
4366*8975f5c5SAndroid Build Coastguard Worker uint32_t layer = 0;
4367*8975f5c5SAndroid Build Coastguard Worker uint32_t layerCount = 1;
4368*8975f5c5SAndroid Build Coastguard Worker
4369*8975f5c5SAndroid Build Coastguard Worker switch (target)
4370*8975f5c5SAndroid Build Coastguard Worker {
4371*8975f5c5SAndroid Build Coastguard Worker case gl::TextureTarget::CubeMapArray:
4372*8975f5c5SAndroid Build Coastguard Worker case gl::TextureTarget::_2DArray:
4373*8975f5c5SAndroid Build Coastguard Worker layerCount = mImage->getLayerCount();
4374*8975f5c5SAndroid Build Coastguard Worker break;
4375*8975f5c5SAndroid Build Coastguard Worker default:
4376*8975f5c5SAndroid Build Coastguard Worker if (gl::IsCubeMapFaceTarget(target))
4377*8975f5c5SAndroid Build Coastguard Worker {
4378*8975f5c5SAndroid Build Coastguard Worker layer = static_cast<uint32_t>(gl::CubeMapTextureTargetToFaceIndex(target));
4379*8975f5c5SAndroid Build Coastguard Worker }
4380*8975f5c5SAndroid Build Coastguard Worker break;
4381*8975f5c5SAndroid Build Coastguard Worker }
4382*8975f5c5SAndroid Build Coastguard Worker
4383*8975f5c5SAndroid Build Coastguard Worker return mImage->readPixelsForGetImage(contextVk, packState, packBuffer, gl::LevelIndex(level),
4384*8975f5c5SAndroid Build Coastguard Worker layer, layerCount, format, type, pixels);
4385*8975f5c5SAndroid Build Coastguard Worker }
4386*8975f5c5SAndroid Build Coastguard Worker
getCompressedTexImage(const gl::Context * context,const gl::PixelPackState & packState,gl::Buffer * packBuffer,gl::TextureTarget target,GLint level,void * pixels)4387*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getCompressedTexImage(const gl::Context *context,
4388*8975f5c5SAndroid Build Coastguard Worker const gl::PixelPackState &packState,
4389*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *packBuffer,
4390*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget target,
4391*8975f5c5SAndroid Build Coastguard Worker GLint level,
4392*8975f5c5SAndroid Build Coastguard Worker void *pixels)
4393*8975f5c5SAndroid Build Coastguard Worker {
4394*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk = vk::GetImpl(context);
4395*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
4396*8975f5c5SAndroid Build Coastguard Worker
4397*8975f5c5SAndroid Build Coastguard Worker GLint baseLevel = static_cast<int>(mState.getBaseLevel());
4398*8975f5c5SAndroid Build Coastguard Worker if (level < baseLevel || level >= baseLevel + static_cast<int>(mState.getEnabledLevelCount()))
4399*8975f5c5SAndroid Build Coastguard Worker {
4400*8975f5c5SAndroid Build Coastguard Worker // TODO(http://anglebug.com/42264855): Handle inconsistent textures.
4401*8975f5c5SAndroid Build Coastguard Worker WARN() << "GetCompressedTexImage for inconsistent texture levels is not implemented.";
4402*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
4403*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4404*8975f5c5SAndroid Build Coastguard Worker }
4405*8975f5c5SAndroid Build Coastguard Worker
4406*8975f5c5SAndroid Build Coastguard Worker uint32_t layer = 0;
4407*8975f5c5SAndroid Build Coastguard Worker uint32_t layerCount = 1;
4408*8975f5c5SAndroid Build Coastguard Worker
4409*8975f5c5SAndroid Build Coastguard Worker switch (target)
4410*8975f5c5SAndroid Build Coastguard Worker {
4411*8975f5c5SAndroid Build Coastguard Worker case gl::TextureTarget::CubeMapArray:
4412*8975f5c5SAndroid Build Coastguard Worker case gl::TextureTarget::_2DArray:
4413*8975f5c5SAndroid Build Coastguard Worker layerCount = mImage->getLayerCount();
4414*8975f5c5SAndroid Build Coastguard Worker break;
4415*8975f5c5SAndroid Build Coastguard Worker default:
4416*8975f5c5SAndroid Build Coastguard Worker if (gl::IsCubeMapFaceTarget(target))
4417*8975f5c5SAndroid Build Coastguard Worker {
4418*8975f5c5SAndroid Build Coastguard Worker layer = static_cast<uint32_t>(gl::CubeMapTextureTargetToFaceIndex(target));
4419*8975f5c5SAndroid Build Coastguard Worker }
4420*8975f5c5SAndroid Build Coastguard Worker break;
4421*8975f5c5SAndroid Build Coastguard Worker }
4422*8975f5c5SAndroid Build Coastguard Worker
4423*8975f5c5SAndroid Build Coastguard Worker return mImage->readPixelsForCompressedGetImage(
4424*8975f5c5SAndroid Build Coastguard Worker contextVk, packState, packBuffer, gl::LevelIndex(level), layer, layerCount, pixels);
4425*8975f5c5SAndroid Build Coastguard Worker }
4426*8975f5c5SAndroid Build Coastguard Worker
getBaseLevelFormat(vk::Renderer * renderer) const4427*8975f5c5SAndroid Build Coastguard Worker const vk::Format &TextureVk::getBaseLevelFormat(vk::Renderer *renderer) const
4428*8975f5c5SAndroid Build Coastguard Worker {
4429*8975f5c5SAndroid Build Coastguard Worker const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
4430*8975f5c5SAndroid Build Coastguard Worker return renderer->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
4431*8975f5c5SAndroid Build Coastguard Worker }
4432*8975f5c5SAndroid Build Coastguard Worker
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)4433*8975f5c5SAndroid Build Coastguard Worker void TextureVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
4434*8975f5c5SAndroid Build Coastguard Worker {
4435*8975f5c5SAndroid Build Coastguard Worker ASSERT(index == kTextureImageSubjectIndex &&
4436*8975f5c5SAndroid Build Coastguard Worker (message == angle::SubjectMessage::SubjectChanged ||
4437*8975f5c5SAndroid Build Coastguard Worker message == angle::SubjectMessage::InitializationComplete));
4438*8975f5c5SAndroid Build Coastguard Worker
4439*8975f5c5SAndroid Build Coastguard Worker // Forward the notification to the parent that the staging buffer changed.
4440*8975f5c5SAndroid Build Coastguard Worker onStateChange(message);
4441*8975f5c5SAndroid Build Coastguard Worker }
4442*8975f5c5SAndroid Build Coastguard Worker
getImageViewSubresourceSerialImpl(vk::ImageViewColorspace colorspace) const4443*8975f5c5SAndroid Build Coastguard Worker vk::ImageOrBufferViewSubresourceSerial TextureVk::getImageViewSubresourceSerialImpl(
4444*8975f5c5SAndroid Build Coastguard Worker vk::ImageViewColorspace colorspace) const
4445*8975f5c5SAndroid Build Coastguard Worker {
4446*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel());
4447*8975f5c5SAndroid Build Coastguard Worker // getMipmapMaxLevel will clamp to the max level if it is smaller than the number of mips.
4448*8975f5c5SAndroid Build Coastguard Worker uint32_t levelCount = gl::LevelIndex(mState.getMipmapMaxLevel()) - baseLevel + 1;
4449*8975f5c5SAndroid Build Coastguard Worker
4450*8975f5c5SAndroid Build Coastguard Worker return getImageViews().getSubresourceSerialForColorspace(baseLevel, levelCount, 0,
4451*8975f5c5SAndroid Build Coastguard Worker vk::LayerMode::All, colorspace);
4452*8975f5c5SAndroid Build Coastguard Worker }
4453*8975f5c5SAndroid Build Coastguard Worker
getBufferViewSerial() const4454*8975f5c5SAndroid Build Coastguard Worker vk::ImageOrBufferViewSubresourceSerial TextureVk::getBufferViewSerial() const
4455*8975f5c5SAndroid Build Coastguard Worker {
4456*8975f5c5SAndroid Build Coastguard Worker return mBufferViews.getSerial();
4457*8975f5c5SAndroid Build Coastguard Worker }
4458*8975f5c5SAndroid Build Coastguard Worker
getStorageImageViewSerial(const gl::ImageUnit & binding) const4459*8975f5c5SAndroid Build Coastguard Worker vk::ImageOrBufferViewSubresourceSerial TextureVk::getStorageImageViewSerial(
4460*8975f5c5SAndroid Build Coastguard Worker const gl::ImageUnit &binding) const
4461*8975f5c5SAndroid Build Coastguard Worker {
4462*8975f5c5SAndroid Build Coastguard Worker vk::LayerMode layerMode = binding.layered == GL_TRUE ? vk::LayerMode::All : vk::LayerMode::_1;
4463*8975f5c5SAndroid Build Coastguard Worker uint32_t frontendLayer = binding.layered == GL_TRUE ? 0 : static_cast<uint32_t>(binding.layer);
4464*8975f5c5SAndroid Build Coastguard Worker uint32_t nativeLayer = getNativeImageLayer(frontendLayer);
4465*8975f5c5SAndroid Build Coastguard Worker
4466*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex baseLevel(
4467*8975f5c5SAndroid Build Coastguard Worker getNativeImageLevel(gl::LevelIndex(static_cast<uint32_t>(binding.level))));
4468*8975f5c5SAndroid Build Coastguard Worker
4469*8975f5c5SAndroid Build Coastguard Worker return getImageViews().getSubresourceSerial(baseLevel, 1, nativeLayer, layerMode);
4470*8975f5c5SAndroid Build Coastguard Worker }
4471*8975f5c5SAndroid Build Coastguard Worker
getImageViewLayerCount() const4472*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getImageViewLayerCount() const
4473*8975f5c5SAndroid Build Coastguard Worker {
4474*8975f5c5SAndroid Build Coastguard Worker // We use a special layer count here to handle EGLImages. They might only be
4475*8975f5c5SAndroid Build Coastguard Worker // looking at one layer of a cube or 2D array texture.
4476*8975f5c5SAndroid Build Coastguard Worker return mEGLImageNativeType == gl::TextureType::InvalidEnum ? mImage->getLayerCount() : 1;
4477*8975f5c5SAndroid Build Coastguard Worker }
4478*8975f5c5SAndroid Build Coastguard Worker
getImageViewLevelCount() const4479*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getImageViewLevelCount() const
4480*8975f5c5SAndroid Build Coastguard Worker {
4481*8975f5c5SAndroid Build Coastguard Worker // We use a special level count here to handle EGLImages. They might only be
4482*8975f5c5SAndroid Build Coastguard Worker // looking at one level of the texture's mipmap chain.
4483*8975f5c5SAndroid Build Coastguard Worker return mEGLImageNativeType == gl::TextureType::InvalidEnum ? mImage->getLevelCount() : 1;
4484*8975f5c5SAndroid Build Coastguard Worker }
4485*8975f5c5SAndroid Build Coastguard Worker
refreshImageViews(ContextVk * contextVk)4486*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::refreshImageViews(ContextVk *contextVk)
4487*8975f5c5SAndroid Build Coastguard Worker {
4488*8975f5c5SAndroid Build Coastguard Worker vk::ImageViewHelper &imageView = getImageViews();
4489*8975f5c5SAndroid Build Coastguard Worker if (mImage == nullptr)
4490*8975f5c5SAndroid Build Coastguard Worker {
4491*8975f5c5SAndroid Build Coastguard Worker ASSERT(imageView.isImageViewGarbageEmpty());
4492*8975f5c5SAndroid Build Coastguard Worker }
4493*8975f5c5SAndroid Build Coastguard Worker else
4494*8975f5c5SAndroid Build Coastguard Worker {
4495*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
4496*8975f5c5SAndroid Build Coastguard Worker imageView.release(renderer, mImage->getResourceUse());
4497*8975f5c5SAndroid Build Coastguard Worker
4498*8975f5c5SAndroid Build Coastguard Worker // Since view has changed, some descriptorSet cache maybe obsolete. SO proactively release
4499*8975f5c5SAndroid Build Coastguard Worker // cache.
4500*8975f5c5SAndroid Build Coastguard Worker mDescriptorSetCacheManager.releaseKeys(renderer);
4501*8975f5c5SAndroid Build Coastguard Worker
4502*8975f5c5SAndroid Build Coastguard Worker for (auto &renderTargets : mSingleLayerRenderTargets)
4503*8975f5c5SAndroid Build Coastguard Worker {
4504*8975f5c5SAndroid Build Coastguard Worker for (RenderTargetVector &renderTargetLevels : renderTargets)
4505*8975f5c5SAndroid Build Coastguard Worker {
4506*8975f5c5SAndroid Build Coastguard Worker for (RenderTargetVk &renderTargetVk : renderTargetLevels)
4507*8975f5c5SAndroid Build Coastguard Worker {
4508*8975f5c5SAndroid Build Coastguard Worker renderTargetVk.releaseFramebuffers(contextVk);
4509*8975f5c5SAndroid Build Coastguard Worker }
4510*8975f5c5SAndroid Build Coastguard Worker }
4511*8975f5c5SAndroid Build Coastguard Worker }
4512*8975f5c5SAndroid Build Coastguard Worker for (auto &renderTargetPair : mMultiLayerRenderTargets)
4513*8975f5c5SAndroid Build Coastguard Worker {
4514*8975f5c5SAndroid Build Coastguard Worker renderTargetPair.second->releaseFramebuffers(contextVk);
4515*8975f5c5SAndroid Build Coastguard Worker }
4516*8975f5c5SAndroid Build Coastguard Worker }
4517*8975f5c5SAndroid Build Coastguard Worker
4518*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));
4519*8975f5c5SAndroid Build Coastguard Worker
4520*8975f5c5SAndroid Build Coastguard Worker // Let any Framebuffers know we need to refresh the RenderTarget cache.
4521*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SubjectChanged);
4522*8975f5c5SAndroid Build Coastguard Worker
4523*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4524*8975f5c5SAndroid Build Coastguard Worker }
4525*8975f5c5SAndroid Build Coastguard Worker
ensureMutable(ContextVk * contextVk)4526*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureMutable(ContextVk *contextVk)
4527*8975f5c5SAndroid Build Coastguard Worker {
4528*8975f5c5SAndroid Build Coastguard Worker if (mRequiresMutableStorage)
4529*8975f5c5SAndroid Build Coastguard Worker {
4530*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4531*8975f5c5SAndroid Build Coastguard Worker }
4532*8975f5c5SAndroid Build Coastguard Worker
4533*8975f5c5SAndroid Build Coastguard Worker mRequiresMutableStorage = true;
4534*8975f5c5SAndroid Build Coastguard Worker mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
4535*8975f5c5SAndroid Build Coastguard Worker
4536*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(respecifyImageStorage(contextVk));
4537*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
4538*8975f5c5SAndroid Build Coastguard Worker
4539*8975f5c5SAndroid Build Coastguard Worker return refreshImageViews(contextVk);
4540*8975f5c5SAndroid Build Coastguard Worker }
4541*8975f5c5SAndroid Build Coastguard Worker
ensureRenderable(ContextVk * contextVk,TextureUpdateResult * updateResultOut)4542*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureRenderable(ContextVk *contextVk,
4543*8975f5c5SAndroid Build Coastguard Worker TextureUpdateResult *updateResultOut)
4544*8975f5c5SAndroid Build Coastguard Worker {
4545*8975f5c5SAndroid Build Coastguard Worker return ensureRenderableWithFormat(contextVk, getBaseLevelFormat(contextVk->getRenderer()),
4546*8975f5c5SAndroid Build Coastguard Worker updateResultOut);
4547*8975f5c5SAndroid Build Coastguard Worker }
4548*8975f5c5SAndroid Build Coastguard Worker
ensureRenderableWithFormat(ContextVk * contextVk,const vk::Format & format,TextureUpdateResult * updateResultOut)4549*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureRenderableWithFormat(ContextVk *contextVk,
4550*8975f5c5SAndroid Build Coastguard Worker const vk::Format &format,
4551*8975f5c5SAndroid Build Coastguard Worker TextureUpdateResult *updateResultOut)
4552*8975f5c5SAndroid Build Coastguard Worker {
4553*8975f5c5SAndroid Build Coastguard Worker if (mRequiredImageAccess == vk::ImageAccess::Renderable)
4554*8975f5c5SAndroid Build Coastguard Worker {
4555*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4556*8975f5c5SAndroid Build Coastguard Worker }
4557*8975f5c5SAndroid Build Coastguard Worker
4558*8975f5c5SAndroid Build Coastguard Worker mRequiredImageAccess = vk::ImageAccess::Renderable;
4559*8975f5c5SAndroid Build Coastguard Worker if (!mImage)
4560*8975f5c5SAndroid Build Coastguard Worker {
4561*8975f5c5SAndroid Build Coastguard Worker // Later on when ensureImageAllocated() is called, it will ensure a renderable format is
4562*8975f5c5SAndroid Build Coastguard Worker // used.
4563*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4564*8975f5c5SAndroid Build Coastguard Worker }
4565*8975f5c5SAndroid Build Coastguard Worker
4566*8975f5c5SAndroid Build Coastguard Worker if (!format.hasRenderableImageFallbackFormat())
4567*8975f5c5SAndroid Build Coastguard Worker {
4568*8975f5c5SAndroid Build Coastguard Worker // If there is no fallback format for renderable, then nothing to do.
4569*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4570*8975f5c5SAndroid Build Coastguard Worker }
4571*8975f5c5SAndroid Build Coastguard Worker
4572*8975f5c5SAndroid Build Coastguard Worker // luminance/alpha format never fallback for rendering and if we ever do fallback, the
4573*8975f5c5SAndroid Build Coastguard Worker // following code may not handle it properly.
4574*8975f5c5SAndroid Build Coastguard Worker ASSERT(!format.getIntendedFormat().isLUMA());
4575*8975f5c5SAndroid Build Coastguard Worker
4576*8975f5c5SAndroid Build Coastguard Worker angle::FormatID previousActualFormatID =
4577*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(vk::ImageAccess::SampleOnly);
4578*8975f5c5SAndroid Build Coastguard Worker angle::FormatID actualFormatID = format.getActualImageFormatID(vk::ImageAccess::Renderable);
4579*8975f5c5SAndroid Build Coastguard Worker
4580*8975f5c5SAndroid Build Coastguard Worker if (!mImage->valid())
4581*8975f5c5SAndroid Build Coastguard Worker {
4582*8975f5c5SAndroid Build Coastguard Worker // Immutable texture must already have a valid image
4583*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.getImmutableFormat());
4584*8975f5c5SAndroid Build Coastguard Worker // If we have staged updates and they were encoded with different format, we need to flush
4585*8975f5c5SAndroid Build Coastguard Worker // out these staged updates. The respecifyImageStorage should handle reading back the
4586*8975f5c5SAndroid Build Coastguard Worker // flushed data and re-stage it with the new format.
4587*8975f5c5SAndroid Build Coastguard Worker angle::FormatID intendedFormatID = format.getIntendedFormatID();
4588*8975f5c5SAndroid Build Coastguard Worker
4589*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex levelGLStart, levelGLEnd;
4590*8975f5c5SAndroid Build Coastguard Worker ImageMipLevels mipLevels;
4591*8975f5c5SAndroid Build Coastguard Worker if (mState.getImmutableFormat())
4592*8975f5c5SAndroid Build Coastguard Worker {
4593*8975f5c5SAndroid Build Coastguard Worker levelGLStart = gl::LevelIndex(0);
4594*8975f5c5SAndroid Build Coastguard Worker levelGLEnd = gl::LevelIndex(mState.getImmutableLevels());
4595*8975f5c5SAndroid Build Coastguard Worker mipLevels = ImageMipLevels::FullMipChainForGenerateMipmap;
4596*8975f5c5SAndroid Build Coastguard Worker }
4597*8975f5c5SAndroid Build Coastguard Worker else
4598*8975f5c5SAndroid Build Coastguard Worker {
4599*8975f5c5SAndroid Build Coastguard Worker levelGLStart = gl::LevelIndex(mState.getEffectiveBaseLevel());
4600*8975f5c5SAndroid Build Coastguard Worker levelGLEnd =
4601*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex(levelGLStart + getMipLevelCount(ImageMipLevels::EnabledLevels));
4602*8975f5c5SAndroid Build Coastguard Worker mipLevels = ImageMipLevels::EnabledLevels;
4603*8975f5c5SAndroid Build Coastguard Worker }
4604*8975f5c5SAndroid Build Coastguard Worker
4605*8975f5c5SAndroid Build Coastguard Worker if (mImage->hasStagedImageUpdatesWithMismatchedFormat(levelGLStart, levelGLEnd,
4606*8975f5c5SAndroid Build Coastguard Worker actualFormatID))
4607*8975f5c5SAndroid Build Coastguard Worker {
4608*8975f5c5SAndroid Build Coastguard Worker angle::FormatID sampleOnlyFormatID =
4609*8975f5c5SAndroid Build Coastguard Worker format.getActualImageFormatID(vk::ImageAccess::SampleOnly);
4610*8975f5c5SAndroid Build Coastguard Worker
4611*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initImage(contextVk, intendedFormatID, sampleOnlyFormatID, mipLevels));
4612*8975f5c5SAndroid Build Coastguard Worker }
4613*8975f5c5SAndroid Build Coastguard Worker else
4614*8975f5c5SAndroid Build Coastguard Worker {
4615*8975f5c5SAndroid Build Coastguard Worker // First try to convert any staged buffer updates from old format to new format using
4616*8975f5c5SAndroid Build Coastguard Worker // CPU.
4617*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImage->reformatStagedBufferUpdates(contextVk, previousActualFormatID,
4618*8975f5c5SAndroid Build Coastguard Worker actualFormatID));
4619*8975f5c5SAndroid Build Coastguard Worker }
4620*8975f5c5SAndroid Build Coastguard Worker }
4621*8975f5c5SAndroid Build Coastguard Worker
4622*8975f5c5SAndroid Build Coastguard Worker // Make sure we update mImageUsage bits
4623*8975f5c5SAndroid Build Coastguard Worker const bool imageWasInitialized = mImage->valid();
4624*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageAllocated(contextVk, format));
4625*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(respecifyImageStorage(contextVk));
4626*8975f5c5SAndroid Build Coastguard Worker if (imageWasInitialized)
4627*8975f5c5SAndroid Build Coastguard Worker {
4628*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
4629*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(refreshImageViews(contextVk));
4630*8975f5c5SAndroid Build Coastguard Worker }
4631*8975f5c5SAndroid Build Coastguard Worker
4632*8975f5c5SAndroid Build Coastguard Worker if (updateResultOut != nullptr)
4633*8975f5c5SAndroid Build Coastguard Worker {
4634*8975f5c5SAndroid Build Coastguard Worker *updateResultOut = TextureUpdateResult::ImageRespecified;
4635*8975f5c5SAndroid Build Coastguard Worker }
4636*8975f5c5SAndroid Build Coastguard Worker
4637*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4638*8975f5c5SAndroid Build Coastguard Worker }
4639*8975f5c5SAndroid Build Coastguard Worker
ensureRenderableIfCopyTextureCannotTransfer(ContextVk * contextVk,const gl::InternalFormat & dstFormat,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,TextureVk * source)4640*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureRenderableIfCopyTextureCannotTransfer(
4641*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk,
4642*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &dstFormat,
4643*8975f5c5SAndroid Build Coastguard Worker bool unpackFlipY,
4644*8975f5c5SAndroid Build Coastguard Worker bool unpackPremultiplyAlpha,
4645*8975f5c5SAndroid Build Coastguard Worker bool unpackUnmultiplyAlpha,
4646*8975f5c5SAndroid Build Coastguard Worker TextureVk *source)
4647*8975f5c5SAndroid Build Coastguard Worker {
4648*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
4649*8975f5c5SAndroid Build Coastguard Worker
4650*8975f5c5SAndroid Build Coastguard Worker VkImageTiling srcTilingMode = source->getImage().getTilingMode();
4651*8975f5c5SAndroid Build Coastguard Worker const vk::Format &dstVkFormat = renderer->getFormat(dstFormat.sizedInternalFormat);
4652*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstFormatID = dstVkFormat.getActualImageFormatID(getRequiredImageAccess());
4653*8975f5c5SAndroid Build Coastguard Worker VkImageTiling dstTilingMode = getTilingMode();
4654*8975f5c5SAndroid Build Coastguard Worker
4655*8975f5c5SAndroid Build Coastguard Worker if (!CanCopyWithTransferForCopyTexture(
4656*8975f5c5SAndroid Build Coastguard Worker renderer, source->getImage(), srcTilingMode, dstVkFormat.getIntendedFormatID(),
4657*8975f5c5SAndroid Build Coastguard Worker dstFormatID, dstTilingMode, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
4658*8975f5c5SAndroid Build Coastguard Worker {
4659*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderableWithFormat(contextVk, dstVkFormat, nullptr));
4660*8975f5c5SAndroid Build Coastguard Worker }
4661*8975f5c5SAndroid Build Coastguard Worker
4662*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4663*8975f5c5SAndroid Build Coastguard Worker }
4664*8975f5c5SAndroid Build Coastguard Worker
ensureRenderableIfCopyTexImageCannotTransfer(ContextVk * contextVk,const gl::InternalFormat & dstFormat,gl::Framebuffer * source)4665*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureRenderableIfCopyTexImageCannotTransfer(
4666*8975f5c5SAndroid Build Coastguard Worker ContextVk *contextVk,
4667*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &dstFormat,
4668*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *source)
4669*8975f5c5SAndroid Build Coastguard Worker {
4670*8975f5c5SAndroid Build Coastguard Worker vk::Renderer *renderer = contextVk->getRenderer();
4671*8975f5c5SAndroid Build Coastguard Worker FramebufferVk *framebufferVk = vk::GetImpl(source);
4672*8975f5c5SAndroid Build Coastguard Worker
4673*8975f5c5SAndroid Build Coastguard Worker RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
4674*8975f5c5SAndroid Build Coastguard Worker
4675*8975f5c5SAndroid Build Coastguard Worker angle::FormatID srcIntendedFormatID = colorReadRT->getImageIntendedFormatID();
4676*8975f5c5SAndroid Build Coastguard Worker angle::FormatID srcActualFormatID = colorReadRT->getImageActualFormatID();
4677*8975f5c5SAndroid Build Coastguard Worker VkImageTiling srcTilingMode = colorReadRT->getImageForCopy().getTilingMode();
4678*8975f5c5SAndroid Build Coastguard Worker const vk::Format &dstVkFormat = renderer->getFormat(dstFormat.sizedInternalFormat);
4679*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstIntendedFormatID = dstVkFormat.getIntendedFormatID();
4680*8975f5c5SAndroid Build Coastguard Worker angle::FormatID dstActualFormatID =
4681*8975f5c5SAndroid Build Coastguard Worker dstVkFormat.getActualImageFormatID(getRequiredImageAccess());
4682*8975f5c5SAndroid Build Coastguard Worker VkImageTiling destTilingMode = getTilingMode();
4683*8975f5c5SAndroid Build Coastguard Worker
4684*8975f5c5SAndroid Build Coastguard Worker bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO();
4685*8975f5c5SAndroid Build Coastguard Worker
4686*8975f5c5SAndroid Build Coastguard Worker if (!CanCopyWithTransferForTexImage(renderer, srcIntendedFormatID, srcActualFormatID,
4687*8975f5c5SAndroid Build Coastguard Worker srcTilingMode, dstIntendedFormatID, dstActualFormatID,
4688*8975f5c5SAndroid Build Coastguard Worker destTilingMode, isViewportFlipY))
4689*8975f5c5SAndroid Build Coastguard Worker {
4690*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureRenderableWithFormat(contextVk, dstVkFormat, nullptr));
4691*8975f5c5SAndroid Build Coastguard Worker }
4692*8975f5c5SAndroid Build Coastguard Worker
4693*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
4694*8975f5c5SAndroid Build Coastguard Worker }
4695*8975f5c5SAndroid Build Coastguard Worker
stageSelfAsSubresourceUpdates(ContextVk * contextVk)4696*8975f5c5SAndroid Build Coastguard Worker void TextureVk::stageSelfAsSubresourceUpdates(ContextVk *contextVk)
4697*8975f5c5SAndroid Build Coastguard Worker {
4698*8975f5c5SAndroid Build Coastguard Worker // If we are calling stageSelfAsSubresourceUpdates(), the current image will be swapped
4699*8975f5c5SAndroid Build Coastguard Worker // to prevImage in stageSelfAsSubresourceUpdates(), therefore we need to release the
4700*8975f5c5SAndroid Build Coastguard Worker // imageViews first as we want to use current image.mUse to keep track of imageViews' resource
4701*8975f5c5SAndroid Build Coastguard Worker // lifetime.
4702*8975f5c5SAndroid Build Coastguard Worker releaseImageViews(contextVk);
4703*8975f5c5SAndroid Build Coastguard Worker // Make the image stage itself as updates to its levels.
4704*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mImageSiblingSerial.valid());
4705*8975f5c5SAndroid Build Coastguard Worker mImage->stageSelfAsSubresourceUpdates(contextVk, mImage->getLevelCount(), mState.getType(),
4706*8975f5c5SAndroid Build Coastguard Worker mRedefinedLevels);
4707*8975f5c5SAndroid Build Coastguard Worker }
4708*8975f5c5SAndroid Build Coastguard Worker
updateCachedImageViewSerials()4709*8975f5c5SAndroid Build Coastguard Worker void TextureVk::updateCachedImageViewSerials()
4710*8975f5c5SAndroid Build Coastguard Worker {
4711*8975f5c5SAndroid Build Coastguard Worker mCachedImageViewSubresourceSerialSRGBDecode =
4712*8975f5c5SAndroid Build Coastguard Worker getImageViewSubresourceSerialImpl(vk::ImageViewColorspace::SRGB);
4713*8975f5c5SAndroid Build Coastguard Worker mCachedImageViewSubresourceSerialSkipDecode =
4714*8975f5c5SAndroid Build Coastguard Worker getImageViewSubresourceSerialImpl(vk::ImageViewColorspace::Linear);
4715*8975f5c5SAndroid Build Coastguard Worker }
4716*8975f5c5SAndroid Build Coastguard Worker } // namespace rx
4717