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 | #include "VkImageView.hpp" |
16 | #include "VkImage.hpp" |
17 | #include <System/Math.hpp> |
18 | |
19 | namespace |
20 | { |
21 | VkComponentMapping ResolveComponentMapping(VkComponentMapping m, vk::Format format) |
22 | { |
23 | m = vk::ResolveIdentityMapping(m); |
24 | |
25 | // Replace non-present components with zero/one swizzles so that the sampler |
26 | // will give us correct interactions between channel replacement and texel replacement, |
27 | // where we've had to invent new channels behind the app's back (eg transparent decompression |
28 | // of ETC2 RGB -> BGRA8) |
29 | VkComponentSwizzle table[] = { |
30 | VK_COMPONENT_SWIZZLE_IDENTITY, |
31 | VK_COMPONENT_SWIZZLE_ZERO, |
32 | VK_COMPONENT_SWIZZLE_ONE, |
33 | VK_COMPONENT_SWIZZLE_R, |
34 | format.componentCount() < 2 ? VK_COMPONENT_SWIZZLE_ZERO : VK_COMPONENT_SWIZZLE_G, |
35 | format.componentCount() < 3 ? VK_COMPONENT_SWIZZLE_ZERO : VK_COMPONENT_SWIZZLE_B, |
36 | format.componentCount() < 4 ? VK_COMPONENT_SWIZZLE_ONE : VK_COMPONENT_SWIZZLE_A, |
37 | }; |
38 | |
39 | return {table[m.r], table[m.g], table[m.b], table[m.a]}; |
40 | } |
41 | |
42 | VkImageSubresourceRange ResolveRemainingLevelsLayers(VkImageSubresourceRange range, const vk::Image *image) |
43 | { |
44 | return { |
45 | range.aspectMask, |
46 | range.baseMipLevel, |
47 | (range.levelCount == VK_REMAINING_MIP_LEVELS) ? (image->getMipLevels() - range.baseMipLevel) : range.levelCount, |
48 | range.baseArrayLayer, |
49 | (range.layerCount == VK_REMAINING_ARRAY_LAYERS) ? (image->getArrayLayers() - range.baseArrayLayer) : range.layerCount, |
50 | }; |
51 | } |
52 | } |
53 | |
54 | namespace vk |
55 | { |
56 | |
57 | std::atomic<uint32_t> ImageView::nextID(1); |
58 | |
59 | ImageView::ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem, const vk::SamplerYcbcrConversion *ycbcrConversion) : |
60 | image(vk::Cast(pCreateInfo->image)), viewType(pCreateInfo->viewType), format(pCreateInfo->format), |
61 | components(ResolveComponentMapping(pCreateInfo->components, format)), |
62 | subresourceRange(ResolveRemainingLevelsLayers(pCreateInfo->subresourceRange, image)), |
63 | ycbcrConversion(ycbcrConversion) |
64 | { |
65 | } |
66 | |
67 | size_t ImageView::ComputeRequiredAllocationSize(const VkImageViewCreateInfo* pCreateInfo) |
68 | { |
69 | return 0; |
70 | } |
71 | |
72 | void ImageView::destroy(const VkAllocationCallbacks* pAllocator) |
73 | { |
74 | } |
75 | |
76 | bool ImageView::imageTypesMatch(VkImageType imageType) const |
77 | { |
78 | uint32_t imageArrayLayers = image->getArrayLayers(); |
79 | |
80 | switch(viewType) |
81 | { |
82 | case VK_IMAGE_VIEW_TYPE_1D: |
83 | return (imageType == VK_IMAGE_TYPE_1D) && |
84 | (subresourceRange.layerCount == 1); |
85 | case VK_IMAGE_VIEW_TYPE_1D_ARRAY: |
86 | return imageType == VK_IMAGE_TYPE_1D; |
87 | case VK_IMAGE_VIEW_TYPE_2D: |
88 | return ((imageType == VK_IMAGE_TYPE_2D) || |
89 | ((imageType == VK_IMAGE_TYPE_3D) && |
90 | (imageArrayLayers == 1))) && |
91 | (subresourceRange.layerCount == 1); |
92 | case VK_IMAGE_VIEW_TYPE_2D_ARRAY: |
93 | return (imageType == VK_IMAGE_TYPE_2D) || |
94 | ((imageType == VK_IMAGE_TYPE_3D) && |
95 | (imageArrayLayers == 1)); |
96 | case VK_IMAGE_VIEW_TYPE_CUBE: |
97 | return image->isCube() && |
98 | (imageArrayLayers >= subresourceRange.layerCount) && |
99 | (subresourceRange.layerCount == 6); |
100 | case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: |
101 | return image->isCube() && |
102 | (imageArrayLayers >= subresourceRange.layerCount) && |
103 | (subresourceRange.layerCount >= 6); |
104 | case VK_IMAGE_VIEW_TYPE_3D: |
105 | return (imageType == VK_IMAGE_TYPE_3D) && |
106 | (imageArrayLayers == 1) && |
107 | (subresourceRange.layerCount == 1); |
108 | default: |
109 | UNREACHABLE("Unexpected viewType %d" , (int)viewType); |
110 | } |
111 | |
112 | return false; |
113 | } |
114 | |
115 | void ImageView::clear(const VkClearValue& clearValue, const VkImageAspectFlags aspectMask, const VkRect2D& renderArea) |
116 | { |
117 | // Note: clearing ignores swizzling, so components is ignored. |
118 | |
119 | if(!imageTypesMatch(image->getImageType())) |
120 | { |
121 | UNIMPLEMENTED("imageTypesMatch" ); |
122 | } |
123 | |
124 | if(!format.isCompatible(image->getFormat())) |
125 | { |
126 | UNIMPLEMENTED("incompatible formats" ); |
127 | } |
128 | |
129 | VkImageSubresourceRange sr = subresourceRange; |
130 | sr.aspectMask = aspectMask; |
131 | image->clear(clearValue, format, renderArea, sr); |
132 | } |
133 | |
134 | void ImageView::clear(const VkClearValue& clearValue, const VkImageAspectFlags aspectMask, const VkClearRect& renderArea) |
135 | { |
136 | // Note: clearing ignores swizzling, so components is ignored. |
137 | |
138 | if(!imageTypesMatch(image->getImageType())) |
139 | { |
140 | UNIMPLEMENTED("imageTypesMatch" ); |
141 | } |
142 | |
143 | if(!format.isCompatible(image->getFormat())) |
144 | { |
145 | UNIMPLEMENTED("incompatible formats" ); |
146 | } |
147 | |
148 | VkImageSubresourceRange sr; |
149 | sr.aspectMask = aspectMask; |
150 | sr.baseMipLevel = subresourceRange.baseMipLevel; |
151 | sr.levelCount = subresourceRange.levelCount; |
152 | sr.baseArrayLayer = renderArea.baseArrayLayer + subresourceRange.baseArrayLayer; |
153 | sr.layerCount = renderArea.layerCount; |
154 | |
155 | image->clear(clearValue, format, renderArea.rect, sr); |
156 | } |
157 | |
158 | void ImageView::clearWithLayerMask(const VkClearValue &clearValue, VkImageAspectFlags aspectMask, const VkRect2D &renderArea, uint32_t layerMask) |
159 | { |
160 | while (layerMask) |
161 | { |
162 | uint32_t layer = sw::log2i(layerMask); |
163 | layerMask &= ~(1 << layer); |
164 | VkClearRect r = {renderArea, layer, 1}; |
165 | r.baseArrayLayer = layer; |
166 | clear(clearValue, aspectMask, r); |
167 | } |
168 | } |
169 | |
170 | void ImageView::resolve(ImageView* resolveAttachment, int layer) |
171 | { |
172 | if((subresourceRange.levelCount != 1) || (resolveAttachment->subresourceRange.levelCount != 1)) |
173 | { |
174 | UNIMPLEMENTED("levelCount" ); |
175 | } |
176 | |
177 | VkImageCopy region; |
178 | region.srcSubresource = |
179 | { |
180 | subresourceRange.aspectMask, |
181 | subresourceRange.baseMipLevel, |
182 | subresourceRange.baseArrayLayer + layer, |
183 | 1 |
184 | }; |
185 | region.srcOffset = { 0, 0, 0 }; |
186 | region.dstSubresource = |
187 | { |
188 | resolveAttachment->subresourceRange.aspectMask, |
189 | resolveAttachment->subresourceRange.baseMipLevel, |
190 | resolveAttachment->subresourceRange.baseArrayLayer + layer, |
191 | 1 |
192 | }; |
193 | region.dstOffset = { 0, 0, 0 }; |
194 | region.extent = image->getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask), |
195 | subresourceRange.baseMipLevel); |
196 | |
197 | image->copyTo(resolveAttachment->image, region); |
198 | } |
199 | |
200 | void ImageView::resolve(ImageView* resolveAttachment) |
201 | { |
202 | if((subresourceRange.levelCount != 1) || (resolveAttachment->subresourceRange.levelCount != 1)) |
203 | { |
204 | UNIMPLEMENTED("levelCount" ); |
205 | } |
206 | |
207 | VkImageCopy region; |
208 | region.srcSubresource = |
209 | { |
210 | subresourceRange.aspectMask, |
211 | subresourceRange.baseMipLevel, |
212 | subresourceRange.baseArrayLayer, |
213 | subresourceRange.layerCount |
214 | }; |
215 | region.srcOffset = { 0, 0, 0 }; |
216 | region.dstSubresource = |
217 | { |
218 | resolveAttachment->subresourceRange.aspectMask, |
219 | resolveAttachment->subresourceRange.baseMipLevel, |
220 | resolveAttachment->subresourceRange.baseArrayLayer, |
221 | resolveAttachment->subresourceRange.layerCount |
222 | }; |
223 | region.dstOffset = { 0, 0, 0 }; |
224 | region.extent = image->getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask), |
225 | subresourceRange.baseMipLevel); |
226 | |
227 | image->copyTo(resolveAttachment->image, region); |
228 | } |
229 | |
230 | void ImageView::resolveWithLayerMask(ImageView *resolveAttachment, uint32_t layerMask) |
231 | { |
232 | while (layerMask) |
233 | { |
234 | int layer = sw::log2i(layerMask); |
235 | layerMask &= ~(1 << layer); |
236 | resolve(resolveAttachment, layer); |
237 | } |
238 | } |
239 | |
240 | const Image* ImageView::getImage(Usage usage) const |
241 | { |
242 | switch(usage) |
243 | { |
244 | case RAW: |
245 | return image; |
246 | case SAMPLING: |
247 | return image->getSampledImage(format); |
248 | default: |
249 | UNIMPLEMENTED("usage %d" , int(usage)); |
250 | return nullptr; |
251 | } |
252 | } |
253 | |
254 | Format ImageView::getFormat(Usage usage) const |
255 | { |
256 | Format imageFormat = ((usage == RAW) || (getImage(usage) == image)) ? format : getImage(usage)->getFormat(); |
257 | return imageFormat.getAspectFormat(subresourceRange.aspectMask); |
258 | } |
259 | |
260 | int ImageView::rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage) const |
261 | { |
262 | return getImage(usage)->rowPitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel); |
263 | } |
264 | |
265 | int ImageView::slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage) const |
266 | { |
267 | return getImage(usage)->slicePitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel); |
268 | } |
269 | |
270 | int ImageView::layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage) const |
271 | { |
272 | return static_cast<int>(getImage(usage)->getLayerSize(aspect)); |
273 | } |
274 | |
275 | VkExtent3D ImageView::getMipLevelExtent(uint32_t mipLevel) const |
276 | { |
277 | return image->getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask), |
278 | subresourceRange.baseMipLevel + mipLevel); |
279 | } |
280 | |
281 | void *ImageView::getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer, Usage usage) const |
282 | { |
283 | ASSERT(mipLevel < subresourceRange.levelCount); |
284 | |
285 | VkImageSubresourceLayers imageSubresourceLayers = |
286 | { |
287 | static_cast<VkImageAspectFlags>(aspect), |
288 | subresourceRange.baseMipLevel + mipLevel, |
289 | subresourceRange.baseArrayLayer + layer, |
290 | subresourceRange.layerCount |
291 | }; |
292 | |
293 | return getImage(usage)->getTexelPointer(offset, imageSubresourceLayers); |
294 | } |
295 | |
296 | } |
297 | |