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 int stride = 0;
40 bool externalMemory = false;
41 buffer_handle_t nativeHandle = nullptr;
42 VkSwapchainImageUsageFlagsANDROID androidUsage = 0;
43 };
44 #endif
45
46 class Image : public Object<Image, VkImage>
47 {
48 public:
49 Image(const VkImageCreateInfo *pCreateInfo, void *mem, Device *device);
50 void destroy(const VkAllocationCallbacks *pAllocator);
51
52 #ifdef __ANDROID__
53 VkResult prepareForExternalUseANDROID() const;
54 #endif
55
56 static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo *pCreateInfo);
57
58 const VkMemoryRequirements getMemoryRequirements() 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 VkImageCopy &pRegion) const;
63 void copyTo(Buffer *dstBuffer, const VkBufferImageCopy ®ion);
64 void copyFrom(Buffer *srcBuffer, const VkBufferImageCopy ®ion);
65
66 void blitTo(Image *dstImage, const VkImageBlit ®ion, VkFilter filter) const;
67 void copyTo(uint8_t *dst, unsigned int dstPitch) const;
68 void resolveTo(Image *dstImage, const VkImageResolve ®ion) const;
69 void resolveDepthStencilTo(const ImageView *src, ImageView *dst, const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve) const;
70 void clear(const VkClearValue &clearValue, const vk::Format &viewFormat, const VkRect2D &renderArea, const VkImageSubresourceRange &subresourceRange);
71 void clear(const VkClearColorValue &color, const VkImageSubresourceRange &subresourceRange);
72 void clear(const VkClearDepthStencilValue &color, const VkImageSubresourceRange &subresourceRange);
73
74 // Get the last layer and mipmap level, handling VK_REMAINING_ARRAY_LAYERS and
75 // VK_REMAINING_MIP_LEVELS, respectively. Note VkImageSubresourceLayers does not
76 // allow these symbolic values, so only VkImageSubresourceRange is accepted.
77 uint32_t getLastLayerIndex(const VkImageSubresourceRange &subresourceRange) const;
78 uint32_t getLastMipLevel(const VkImageSubresourceRange &subresourceRange) const;
79
getImageType() const80 VkImageType getImageType() const { return imageType; }
getFormat() const81 const Format &getFormat() const { return format; }
82 Format getFormat(VkImageAspectFlagBits aspect) const;
getArrayLayers() const83 uint32_t getArrayLayers() const { return arrayLayers; }
getMipLevels() const84 uint32_t getMipLevels() const { return mipLevels; }
getUsage() const85 VkImageUsageFlags getUsage() const { return usage; }
getFlags() const86 VkImageCreateFlags getFlags() const { return flags; }
getSampleCountFlagBits() const87 VkSampleCountFlagBits getSampleCountFlagBits() const { return samples; }
getExtent() const88 const VkExtent3D &getExtent() const { return extent; }
89 VkExtent3D getMipLevelExtent(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
90 int rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
91 int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
92 void *getTexelPointer(const VkOffset3D &offset, const VkImageSubresource &subresource) const;
93 bool isCube() const;
94 bool is3DSlice() const;
95 uint8_t *end() const;
96 VkDeviceSize getLayerSize(VkImageAspectFlagBits aspect) const;
97 VkDeviceSize getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
98 bool canBindToMemory(DeviceMemory *pDeviceMemory) const;
99
100 void prepareForSampling(const VkImageSubresourceRange &subresourceRange);
101 enum ContentsChangedContext
102 {
103 DIRECT_MEMORY_ACCESS = 0,
104 USING_STORAGE = 1
105 };
106 void contentsChanged(const VkImageSubresourceRange &subresourceRange, ContentsChangedContext contentsChangedContext = DIRECT_MEMORY_ACCESS);
107 const Image *getSampledImage(const vk::Format &imageViewFormat) const;
108
109 #ifdef __ANDROID__
setBackingMemory(BackingMemory & bm)110 void setBackingMemory(BackingMemory &bm)
111 {
112 backingMemory = bm;
113 }
hasExternalMemory() const114 bool hasExternalMemory() const { return backingMemory.externalMemory; }
115 VkDeviceMemory getExternalMemory() const;
getSupportedExternalMemoryHandleTypes() const116 VkExternalMemoryHandleTypeFlags getSupportedExternalMemoryHandleTypes() const { return supportedExternalMemoryHandleTypes; }
117 #endif
118
119 DeviceMemory *deviceMemory = nullptr;
120
121 private:
122 void copy(Buffer *buffer, const VkBufferImageCopy ®ion, bool bufferIsSource);
123 VkDeviceSize getStorageSize(VkImageAspectFlags flags) const;
124 VkDeviceSize getMultiSampledLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
125 VkDeviceSize getLayerOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
126 VkDeviceSize getMemoryOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
127 VkDeviceSize getMemoryOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) const;
128 VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D &offset, const VkImageSubresource &subresource) const;
129 VkDeviceSize getMemoryOffset(VkImageAspectFlagBits aspect) const;
130 VkExtent3D imageExtentInBlocks(const VkExtent3D &extent, VkImageAspectFlagBits aspect) const;
131 VkOffset3D imageOffsetInBlocks(const VkOffset3D &offset, VkImageAspectFlagBits aspect) const;
132 VkExtent2D bufferExtentInBlocks(const VkExtent2D &extent, const VkBufferImageCopy ®ion) const;
133 VkFormat getClearFormat() const;
134 void clear(void *pixelData, VkFormat pixelFormat, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D &renderArea);
135 int borderSize() const;
136 bool requiresPreprocessing() const;
137 void decompress(const VkImageSubresource &subresource);
138 bool updateCube(const VkImageSubresource &subresource);
139 void decodeETC2(const VkImageSubresource &subresource);
140 void decodeBC(const VkImageSubresource &subresource);
141 void decodeASTC(const VkImageSubresource &subresource);
142
143 const Device *const device = nullptr;
144 VkDeviceSize memoryOffset = 0;
145 VkImageCreateFlags flags = 0;
146 VkImageType imageType = VK_IMAGE_TYPE_2D;
147 Format format;
148 VkExtent3D extent = { 0, 0, 0 };
149 uint32_t mipLevels = 0;
150 uint32_t arrayLayers = 0;
151 VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
152 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
153 VkImageUsageFlags usage = (VkImageUsageFlags)0;
154 Image *decompressedImage = nullptr;
155 #ifdef __ANDROID__
156 BackingMemory backingMemory = {};
157 #endif
158
159 VkExternalMemoryHandleTypeFlags supportedExternalMemoryHandleTypes = (VkExternalMemoryHandleTypeFlags)0;
160
161 // VkImageSubresource wrapper for use in unordered_set
162 class Subresource
163 {
164 public:
Subresource()165 Subresource()
166 : subresource{ (VkImageAspectFlags)0, 0, 0 }
167 {}
Subresource(const VkImageSubresource & subres)168 Subresource(const VkImageSubresource &subres)
169 : subresource(subres)
170 {}
operator VkImageSubresource() const171 inline operator VkImageSubresource() const { return subresource; }
172
operator ==(const Subresource & other) const173 bool operator==(const Subresource &other) const
174 {
175 return (subresource.aspectMask == other.subresource.aspectMask) &&
176 (subresource.mipLevel == other.subresource.mipLevel) &&
177 (subresource.arrayLayer == other.subresource.arrayLayer);
178 };
179
operator ()(const Subresource & other) const180 size_t operator()(const Subresource &other) const
181 {
182 return static_cast<size_t>(other.subresource.aspectMask) ^
183 static_cast<size_t>(other.subresource.mipLevel) ^
184 static_cast<size_t>(other.subresource.arrayLayer);
185 };
186
187 private:
188 VkImageSubresource subresource;
189 };
190
191 marl::mutex mutex;
192 std::unordered_set<Subresource, Subresource> dirtySubresources GUARDED_BY(mutex);
193 };
194
Cast(VkImage object)195 static inline Image *Cast(VkImage object)
196 {
197 return Image::Cast(object);
198 }
199
200 } // namespace vk
201
operator ==(const VkExtent3D & lhs,const VkExtent3D & rhs)202 inline bool operator==(const VkExtent3D &lhs, const VkExtent3D &rhs)
203 {
204 return lhs.width == rhs.width &&
205 lhs.height == rhs.height &&
206 lhs.depth == rhs.depth;
207 }
208
operator !=(const VkExtent3D & lhs,const VkExtent3D & rhs)209 inline bool operator!=(const VkExtent3D &lhs, const VkExtent3D &rhs)
210 {
211 return !(lhs == rhs);
212 }
213
operator ==(const VkOffset3D & lhs,const VkOffset3D & rhs)214 inline bool operator==(const VkOffset3D &lhs, const VkOffset3D &rhs)
215 {
216 return lhs.x == rhs.x &&
217 lhs.y == rhs.y &&
218 lhs.z == rhs.z;
219 }
220
operator !=(const VkOffset3D & lhs,const VkOffset3D & rhs)221 inline bool operator!=(const VkOffset3D &lhs, const VkOffset3D &rhs)
222 {
223 return !(lhs == rhs);
224 }
225
226 #endif // VK_IMAGE_HPP_
227