• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	void getMemoryRequirements(VkMemoryRequirements2 *pMemoryRequirements) const;
60 	size_t getSizeInBytes(const VkImageSubresourceRange &subresourceRange) const;
61 	void getSubresourceLayout(const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) const;
62 	void bind(DeviceMemory *pDeviceMemory, VkDeviceSize pMemoryOffset);
63 	void copyTo(Image *dstImage, const VkImageCopy2KHR &region) const;
64 	void copyTo(Buffer *dstBuffer, const VkBufferImageCopy2KHR &region);
65 	void copyFrom(Buffer *srcBuffer, const VkBufferImageCopy2KHR &region);
66 
67 	void blitTo(Image *dstImage, const VkImageBlit2KHR &region, VkFilter filter) const;
68 	void copyTo(uint8_t *dst, unsigned int dstPitch) const;
69 	void resolveTo(Image *dstImage, const VkImageResolve2KHR &region) const;
70 	void resolveDepthStencilTo(const ImageView *src, ImageView *dst, VkResolveModeFlagBits depthResolveMode, VkResolveModeFlagBits stencilResolveMode) const;
71 	void clear(const VkClearValue &clearValue, const vk::Format &viewFormat, const VkRect2D &renderArea, const VkImageSubresourceRange &subresourceRange);
72 	void clear(const VkClearColorValue &color, const VkImageSubresourceRange &subresourceRange);
73 	void clear(const VkClearDepthStencilValue &color, const VkImageSubresourceRange &subresourceRange);
74 
75 	// Get the last layer and mipmap level, handling VK_REMAINING_ARRAY_LAYERS and
76 	// VK_REMAINING_MIP_LEVELS, respectively. Note VkImageSubresourceLayers does not
77 	// allow these symbolic values, so only VkImageSubresourceRange is accepted.
78 	uint32_t getLastLayerIndex(const VkImageSubresourceRange &subresourceRange) const;
79 	uint32_t getLastMipLevel(const VkImageSubresourceRange &subresourceRange) const;
80 
getImageType() const81 	VkImageType getImageType() const { return imageType; }
getFormat() const82 	const Format &getFormat() const { return format; }
83 	Format getFormat(VkImageAspectFlagBits aspect) const;
getArrayLayers() const84 	uint32_t getArrayLayers() const { return arrayLayers; }
getMipLevels() const85 	uint32_t getMipLevels() const { return mipLevels; }
getUsage() const86 	VkImageUsageFlags getUsage() const { return usage; }
getFlags() const87 	VkImageCreateFlags getFlags() const { return flags; }
getSampleCountFlagBits() const88 	VkSampleCountFlagBits getSampleCountFlagBits() const { return samples; }
getExtent() const89 	const VkExtent3D &getExtent() const { return extent; }
90 	VkExtent3D getMipLevelExtent(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
91 	size_t rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
92 	size_t slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
93 	void *getTexelPointer(const VkOffset3D &offset, const VkImageSubresource &subresource) const;
94 	bool isCubeCompatible() const;
95 	bool is3DSlice() const;
96 	uint8_t *end() const;
97 	VkDeviceSize getLayerSize(VkImageAspectFlagBits aspect) const;
98 	VkDeviceSize getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
99 	bool canBindToMemory(DeviceMemory *pDeviceMemory) const;
100 
101 	void prepareForSampling(const VkImageSubresourceRange &subresourceRange) const;
102 	enum ContentsChangedContext
103 	{
104 		DIRECT_MEMORY_ACCESS = 0,
105 		USING_STORAGE = 1
106 	};
107 	void contentsChanged(const VkImageSubresourceRange &subresourceRange, ContentsChangedContext contentsChangedContext = DIRECT_MEMORY_ACCESS);
108 	const Image *getSampledImage(const vk::Format &imageViewFormat) const;
109 
110 #ifdef __ANDROID__
setBackingMemory(BackingMemory & bm)111 	void setBackingMemory(BackingMemory &bm)
112 	{
113 		backingMemory = bm;
114 	}
hasExternalMemory() const115 	bool hasExternalMemory() const { return backingMemory.externalMemory; }
116 	VkDeviceMemory getExternalMemory() const;
getSupportedExternalMemoryHandleTypes() const117 	VkExternalMemoryHandleTypeFlags getSupportedExternalMemoryHandleTypes() const { return supportedExternalMemoryHandleTypes; }
118 #endif
119 
120 	DeviceMemory *deviceMemory = nullptr;
121 
122 private:
123 	void copy(Buffer *buffer, const VkBufferImageCopy2KHR &region, bool bufferIsSource);
124 	void copySingleAspectTo(Image *dstImage, const VkImageCopy2KHR &region) const;
125 	VkDeviceSize getStorageSize(VkImageAspectFlags flags) const;
126 	VkDeviceSize getMultiSampledLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
127 	VkDeviceSize getLayerOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
128 	VkDeviceSize getMemoryOffset(VkImageAspectFlagBits aspect) const;
129 	VkDeviceSize getAspectOffset(VkImageAspectFlagBits aspect) const;
130 	VkDeviceSize getSubresourceOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) const;
131 	VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D &offset, const VkImageSubresource &subresource) const;
132 	VkExtent3D imageExtentInBlocks(const VkExtent3D &extent, VkImageAspectFlagBits aspect) const;
133 	VkOffset3D imageOffsetInBlocks(const VkOffset3D &offset, VkImageAspectFlagBits aspect) const;
134 	VkExtent2D bufferExtentInBlocks(const VkExtent2D &extent, const VkBufferImageCopy2KHR &region) const;
135 	void clear(const void *pixelData, VkFormat pixelFormat, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea);
136 	int borderSize() const;
137 
138 	bool requiresPreprocessing() const;
139 	void decompress(const VkImageSubresource &subresource) const;
140 	void decodeETC2(const VkImageSubresource &subresource) const;
141 	void decodeBC(const VkImageSubresource &subresource) const;
142 	void decodeASTC(const VkImageSubresource &subresource) const;
143 
144 	const Device *const device = nullptr;
145 	VkDeviceSize memoryOffset = 0;
146 	VkImageCreateFlags flags = 0;
147 	VkImageType imageType = VK_IMAGE_TYPE_2D;
148 	Format format;
149 	VkExtent3D extent = { 0, 0, 0 };
150 	uint32_t mipLevels = 0;
151 	uint32_t arrayLayers = 0;
152 	VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
153 	VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
154 	VkImageUsageFlags usage = (VkImageUsageFlags)0;
155 	Image *decompressedImage = nullptr;
156 #ifdef __ANDROID__
157 	BackingMemory backingMemory = {};
158 #endif
159 
160 	VkExternalMemoryHandleTypeFlags supportedExternalMemoryHandleTypes = (VkExternalMemoryHandleTypeFlags)0;
161 
162 	// VkImageSubresource wrapper for use in unordered_set
163 	class Subresource
164 	{
165 	public:
Subresource()166 		Subresource()
167 		    : subresource{ (VkImageAspectFlags)0, 0, 0 }
168 		{}
Subresource(const VkImageSubresource & subres)169 		Subresource(const VkImageSubresource &subres)
170 		    : subresource(subres)
171 		{}
operator VkImageSubresource() const172 		inline operator VkImageSubresource() const { return subresource; }
173 
operator ==(const Subresource & other) const174 		bool operator==(const Subresource &other) const
175 		{
176 			return (subresource.aspectMask == other.subresource.aspectMask) &&
177 			       (subresource.mipLevel == other.subresource.mipLevel) &&
178 			       (subresource.arrayLayer == other.subresource.arrayLayer);
179 		};
180 
operator ()(const Subresource & other) const181 		size_t operator()(const Subresource &other) const
182 		{
183 			return static_cast<size_t>(other.subresource.aspectMask) ^
184 			       static_cast<size_t>(other.subresource.mipLevel) ^
185 			       static_cast<size_t>(other.subresource.arrayLayer);
186 		};
187 
188 	private:
189 		VkImageSubresource subresource;
190 	};
191 
192 	mutable marl::mutex mutex;
193 	mutable std::unordered_set<Subresource, Subresource> dirtySubresources GUARDED_BY(mutex);
194 };
195 
Cast(VkImage object)196 static inline Image *Cast(VkImage object)
197 {
198 	return Image::Cast(object);
199 }
200 
201 }  // namespace vk
202 
operator ==(const VkExtent3D & lhs,const VkExtent3D & rhs)203 inline bool operator==(const VkExtent3D &lhs, const VkExtent3D &rhs)
204 {
205 	return lhs.width == rhs.width &&
206 	       lhs.height == rhs.height &&
207 	       lhs.depth == rhs.depth;
208 }
209 
operator !=(const VkExtent3D & lhs,const VkExtent3D & rhs)210 inline bool operator!=(const VkExtent3D &lhs, const VkExtent3D &rhs)
211 {
212 	return !(lhs == rhs);
213 }
214 
operator ==(const VkOffset3D & lhs,const VkOffset3D & rhs)215 inline bool operator==(const VkOffset3D &lhs, const VkOffset3D &rhs)
216 {
217 	return lhs.x == rhs.x &&
218 	       lhs.y == rhs.y &&
219 	       lhs.z == rhs.z;
220 }
221 
operator !=(const VkOffset3D & lhs,const VkOffset3D & rhs)222 inline bool operator!=(const VkOffset3D &lhs, const VkOffset3D &rhs)
223 {
224 	return !(lhs == rhs);
225 }
226 
227 #endif  // VK_IMAGE_HPP_
228