1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef VK_IMAGE_HPP_
16 #define VK_IMAGE_HPP_
17
18 #include "VkFormat.hpp"
19 #include "VkObject.hpp"
20
21 #include "marl/mutex.h"
22
23 #ifdef __ANDROID__
24 # include <vulkan/vk_android_native_buffer.h> // For VkSwapchainImageUsageFlagsANDROID and buffer_handle_t
25 #endif
26
27 #include <unordered_set>
28
29 namespace vk {
30
31 class Buffer;
32 class Device;
33 class DeviceMemory;
34 class ImageView;
35
36 #ifdef __ANDROID__
37 struct BackingMemory
38 {
39 bool externalMemory = false;
40 VkSwapchainImageUsageFlagsANDROID androidUsage = 0;
41 VkNativeBufferANDROID nativeBufferInfo = {};
42 };
43 #endif
44
45 class Image : public Object<Image, VkImage>
46 {
47 public:
48 Image(const VkImageCreateInfo *pCreateInfo, void *mem, Device *device);
49 void destroy(const VkAllocationCallbacks *pAllocator);
50
51 #ifdef __ANDROID__
52 VkResult prepareForExternalUseANDROID() const;
53 #endif
54
55 static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo *pCreateInfo);
56
57 const VkMemoryRequirements getMemoryRequirements() const;
58 void getMemoryRequirements(VkMemoryRequirements2 *pMemoryRequirements) const;
59 size_t getSizeInBytes(const VkImageSubresourceRange &subresourceRange) const;
60 void getSubresourceLayout(const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) const;
61 void bind(DeviceMemory *pDeviceMemory, VkDeviceSize pMemoryOffset);
62 void copyTo(Image *dstImage, const VkImageCopy2KHR ®ion) const;
63 void copyTo(Buffer *dstBuffer, const VkBufferImageCopy2KHR ®ion);
64 void copyFrom(Buffer *srcBuffer, const VkBufferImageCopy2KHR ®ion);
65
66 // VK_EXT_host_image_copy variants of copy
67 void copyToMemory(const VkImageToMemoryCopyEXT ®ion);
68 void copyFromMemory(const VkMemoryToImageCopyEXT ®ion);
69
70 void blitTo(Image *dstImage, const VkImageBlit2KHR ®ion, VkFilter filter) const;
71 void copyTo(uint8_t *dst, unsigned int dstPitch) const;
72 void resolveTo(Image *dstImage, const VkImageResolve2KHR ®ion) const;
73 void resolveDepthStencilTo(const ImageView *src, ImageView *dst, VkResolveModeFlagBits depthResolveMode, VkResolveModeFlagBits stencilResolveMode) const;
74 void clear(const VkClearValue &clearValue, const vk::Format &viewFormat, const VkRect2D &renderArea, const VkImageSubresourceRange &subresourceRange);
75 void clear(const VkClearColorValue &color, const VkImageSubresourceRange &subresourceRange);
76 void clear(const VkClearDepthStencilValue &color, const VkImageSubresourceRange &subresourceRange);
77
78 // Get the last layer and mipmap level, handling VK_REMAINING_ARRAY_LAYERS and
79 // VK_REMAINING_MIP_LEVELS, respectively. Note VkImageSubresourceLayers does not
80 // allow these symbolic values, so only VkImageSubresourceRange is accepted.
81 uint32_t getLastLayerIndex(const VkImageSubresourceRange &subresourceRange) const;
82 uint32_t getLastMipLevel(const VkImageSubresourceRange &subresourceRange) const;
83
getImageType() const84 VkImageType getImageType() const { return imageType; }
getFormat() const85 const Format &getFormat() const { return format; }
86 Format getFormat(VkImageAspectFlagBits aspect) const;
getArrayLayers() const87 uint32_t getArrayLayers() const { return arrayLayers; }
getMipLevels() const88 uint32_t getMipLevels() const { return mipLevels; }
getUsage() const89 VkImageUsageFlags getUsage() const { return usage; }
getFlags() const90 VkImageCreateFlags getFlags() const { return flags; }
getSampleCount() const91 VkSampleCountFlagBits getSampleCount() const { return samples; }
getExtent() const92 const VkExtent3D &getExtent() const { return extent; }
93 VkExtent3D getMipLevelExtent(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
94 size_t rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
95 size_t slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
96 void *getTexelPointer(const VkOffset3D &offset, const VkImageSubresource &subresource) const;
97 bool isCubeCompatible() const;
98 bool is3DSlice() const;
99 uint8_t *end() const;
100 VkDeviceSize getLayerSize(VkImageAspectFlagBits aspect) const;
101 VkDeviceSize getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
102 bool canBindToMemory(DeviceMemory *pDeviceMemory) const;
103
104 void prepareForSampling(const VkImageSubresourceRange &subresourceRange) const;
105 enum ContentsChangedContext
106 {
107 DIRECT_MEMORY_ACCESS = 0,
108 USING_STORAGE = 1
109 };
110 void contentsChanged(const VkImageSubresourceRange &subresourceRange, ContentsChangedContext contentsChangedContext = DIRECT_MEMORY_ACCESS);
111 const Image *getSampledImage(const vk::Format &imageViewFormat) const;
112
113 #ifdef __ANDROID__
setBackingMemory(BackingMemory & bm)114 void setBackingMemory(BackingMemory &bm)
115 {
116 backingMemory = bm;
117 }
hasExternalMemory() const118 bool hasExternalMemory() const { return backingMemory.externalMemory; }
119 VkDeviceMemory getExternalMemory() const;
getSupportedExternalMemoryHandleTypes() const120 VkExternalMemoryHandleTypeFlags getSupportedExternalMemoryHandleTypes() const { return supportedExternalMemoryHandleTypes; }
121 #endif
122
123 DeviceMemory *deviceMemory = nullptr;
124
125 private:
126 void copy(const void *srcCopyMemory,
127 void *dstCopyMemory,
128 uint32_t rowLength,
129 uint32_t imageHeight,
130 const VkImageSubresourceLayers &imageSubresource,
131 const VkOffset3D &imageCopyOffset,
132 const VkExtent3D &imageCopyExtent);
133 void copySingleAspectTo(Image *dstImage, const VkImageCopy2KHR ®ion) const;
134 VkDeviceSize getStorageSize(VkImageAspectFlags flags) const;
135 VkDeviceSize getMultiSampledLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
136 VkDeviceSize getLayerOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
137 VkDeviceSize getMemoryOffset(VkImageAspectFlagBits aspect) const;
138 VkDeviceSize getAspectOffset(VkImageAspectFlagBits aspect) const;
139 VkDeviceSize getSubresourceOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) const;
140 VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D &offset, const VkImageSubresource &subresource) const;
141 VkExtent3D imageExtentInBlocks(const VkExtent3D &extent, VkImageAspectFlagBits aspect) const;
142 VkOffset3D imageOffsetInBlocks(const VkOffset3D &offset, VkImageAspectFlagBits aspect) const;
143 VkExtent2D bufferExtentInBlocks(const VkExtent2D &extent, uint32_t rowLength, uint32_t imageHeight, const VkImageSubresourceLayers &imageSubresource, const VkOffset3D &imageOffset) const;
144 void clear(const void *pixelData, VkFormat pixelFormat, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea);
145 int borderSize() const;
146
147 bool requiresPreprocessing() const;
148 void decompress(const VkImageSubresource &subresource) const;
149 void decodeETC2(const VkImageSubresource &subresource) const;
150 void decodeBC(const VkImageSubresource &subresource) const;
151 void decodeASTC(const VkImageSubresource &subresource) const;
152
153 const Device *const device = nullptr;
154 VkDeviceSize memoryOffset = 0;
155 VkImageCreateFlags flags = 0;
156 VkImageType imageType = VK_IMAGE_TYPE_2D;
157 Format format;
158 VkExtent3D extent = { 0, 0, 0 };
159 uint32_t mipLevels = 0;
160 uint32_t arrayLayers = 0;
161 VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
162 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
163 VkImageUsageFlags usage = (VkImageUsageFlags)0;
164 Image *decompressedImage = nullptr;
165 #ifdef __ANDROID__
166 BackingMemory backingMemory = {};
167 #endif
168
169 VkExternalMemoryHandleTypeFlags supportedExternalMemoryHandleTypes = (VkExternalMemoryHandleTypeFlags)0;
170
171 // VkImageSubresource wrapper for use in unordered_set
172 class Subresource
173 {
174 public:
Subresource()175 Subresource()
176 : subresource{ (VkImageAspectFlags)0, 0, 0 }
177 {}
Subresource(const VkImageSubresource & subres)178 Subresource(const VkImageSubresource &subres)
179 : subresource(subres)
180 {}
operator VkImageSubresource() const181 inline operator VkImageSubresource() const { return subresource; }
182
operator ==(const Subresource & other) const183 bool operator==(const Subresource &other) const
184 {
185 return (subresource.aspectMask == other.subresource.aspectMask) &&
186 (subresource.mipLevel == other.subresource.mipLevel) &&
187 (subresource.arrayLayer == other.subresource.arrayLayer);
188 };
189
operator ()(const Subresource & other) const190 size_t operator()(const Subresource &other) const
191 {
192 return static_cast<size_t>(other.subresource.aspectMask) ^
193 static_cast<size_t>(other.subresource.mipLevel) ^
194 static_cast<size_t>(other.subresource.arrayLayer);
195 };
196
197 private:
198 VkImageSubresource subresource;
199 };
200
201 mutable marl::mutex mutex;
202 mutable std::unordered_set<Subresource, Subresource> dirtySubresources GUARDED_BY(mutex);
203 };
204
Cast(VkImage object)205 static inline Image *Cast(VkImage object)
206 {
207 return Image::Cast(object);
208 }
209
210 } // namespace vk
211
operator ==(const VkExtent3D & lhs,const VkExtent3D & rhs)212 inline bool operator==(const VkExtent3D &lhs, const VkExtent3D &rhs)
213 {
214 return lhs.width == rhs.width &&
215 lhs.height == rhs.height &&
216 lhs.depth == rhs.depth;
217 }
218
operator !=(const VkExtent3D & lhs,const VkExtent3D & rhs)219 inline bool operator!=(const VkExtent3D &lhs, const VkExtent3D &rhs)
220 {
221 return !(lhs == rhs);
222 }
223
operator ==(const VkOffset3D & lhs,const VkOffset3D & rhs)224 inline bool operator==(const VkOffset3D &lhs, const VkOffset3D &rhs)
225 {
226 return lhs.x == rhs.x &&
227 lhs.y == rhs.y &&
228 lhs.z == rhs.z;
229 }
230
operator !=(const VkOffset3D & lhs,const VkOffset3D & rhs)231 inline bool operator!=(const VkOffset3D &lhs, const VkOffset3D &rhs)
232 {
233 return !(lhs == rhs);
234 }
235
236 #endif // VK_IMAGE_HPP_
237