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
ResolveComponentMapping(VkComponentMapping m,vk::Format format)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
ResolveRemainingLevelsLayers(VkImageSubresourceRange range,const vk::Image * image)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 } // anonymous namespace
54
55 namespace vk {
56
57 std::atomic<uint32_t> ImageView::nextID(1);
58
ImageView(const VkImageViewCreateInfo * pCreateInfo,void * mem,const vk::SamplerYcbcrConversion * ycbcrConversion)59 ImageView::ImageView(const VkImageViewCreateInfo *pCreateInfo, void *mem, const vk::SamplerYcbcrConversion *ycbcrConversion)
60 : image(vk::Cast(pCreateInfo->image))
61 , viewType(pCreateInfo->viewType)
62 , format(pCreateInfo->format)
63 , components(ResolveComponentMapping(pCreateInfo->components, format))
64 , subresourceRange(ResolveRemainingLevelsLayers(pCreateInfo->subresourceRange, image))
65 , ycbcrConversion(ycbcrConversion)
66 {
67 }
68
ComputeRequiredAllocationSize(const VkImageViewCreateInfo * pCreateInfo)69 size_t ImageView::ComputeRequiredAllocationSize(const VkImageViewCreateInfo *pCreateInfo)
70 {
71 return 0;
72 }
73
destroy(const VkAllocationCallbacks * pAllocator)74 void ImageView::destroy(const VkAllocationCallbacks *pAllocator)
75 {
76 }
77
78 // Vulkan 1.2 Table 8. Image and image view parameter compatibility requirements
imageTypesMatch(VkImageType imageType) const79 bool ImageView::imageTypesMatch(VkImageType imageType) const
80 {
81 uint32_t imageArrayLayers = image->getArrayLayers();
82
83 switch(viewType)
84 {
85 case VK_IMAGE_VIEW_TYPE_1D:
86 return (imageType == VK_IMAGE_TYPE_1D) &&
87 (subresourceRange.layerCount == 1);
88 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
89 return imageType == VK_IMAGE_TYPE_1D;
90 case VK_IMAGE_VIEW_TYPE_2D:
91 return ((imageType == VK_IMAGE_TYPE_2D) ||
92 ((imageType == VK_IMAGE_TYPE_3D) &&
93 (imageArrayLayers == 1))) &&
94 (subresourceRange.layerCount == 1);
95 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
96 return (imageType == VK_IMAGE_TYPE_2D) ||
97 ((imageType == VK_IMAGE_TYPE_3D) &&
98 (imageArrayLayers == 1));
99 case VK_IMAGE_VIEW_TYPE_CUBE:
100 return image->isCube() &&
101 (imageArrayLayers >= subresourceRange.layerCount) &&
102 (subresourceRange.layerCount == 6);
103 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
104 return image->isCube() &&
105 (imageArrayLayers >= subresourceRange.layerCount) &&
106 (subresourceRange.layerCount >= 6);
107 case VK_IMAGE_VIEW_TYPE_3D:
108 return (imageType == VK_IMAGE_TYPE_3D) &&
109 (imageArrayLayers == 1) &&
110 (subresourceRange.layerCount == 1);
111 default:
112 UNREACHABLE("Unexpected viewType %d", (int)viewType);
113 }
114
115 return false;
116 }
117
clear(const VkClearValue & clearValue,const VkImageAspectFlags aspectMask,const VkRect2D & renderArea)118 void ImageView::clear(const VkClearValue &clearValue, const VkImageAspectFlags aspectMask, const VkRect2D &renderArea)
119 {
120 // Note: clearing ignores swizzling, so components is ignored.
121
122 ASSERT(imageTypesMatch(image->getImageType()));
123 ASSERT(format.isCompatible(image->getFormat()));
124
125 VkImageSubresourceRange sr = subresourceRange;
126 sr.aspectMask = aspectMask;
127 image->clear(clearValue, format, renderArea, sr);
128 }
129
clear(const VkClearValue & clearValue,const VkImageAspectFlags aspectMask,const VkClearRect & renderArea)130 void ImageView::clear(const VkClearValue &clearValue, const VkImageAspectFlags aspectMask, const VkClearRect &renderArea)
131 {
132 // Note: clearing ignores swizzling, so components is ignored.
133
134 ASSERT(imageTypesMatch(image->getImageType()));
135 ASSERT(format.isCompatible(image->getFormat()));
136
137 VkImageSubresourceRange sr;
138 sr.aspectMask = aspectMask;
139 sr.baseMipLevel = subresourceRange.baseMipLevel;
140 sr.levelCount = subresourceRange.levelCount;
141 sr.baseArrayLayer = renderArea.baseArrayLayer + subresourceRange.baseArrayLayer;
142 sr.layerCount = renderArea.layerCount;
143
144 image->clear(clearValue, format, renderArea.rect, sr);
145 }
146
clearWithLayerMask(const VkClearValue & clearValue,VkImageAspectFlags aspectMask,const VkRect2D & renderArea,uint32_t layerMask)147 void ImageView::clearWithLayerMask(const VkClearValue &clearValue, VkImageAspectFlags aspectMask, const VkRect2D &renderArea, uint32_t layerMask)
148 {
149 while(layerMask)
150 {
151 uint32_t layer = sw::log2i(layerMask);
152 layerMask &= ~(1 << layer);
153 VkClearRect r = { renderArea, layer, 1 };
154 r.baseArrayLayer = layer;
155 clear(clearValue, aspectMask, r);
156 }
157 }
158
resolve(ImageView * resolveAttachment,int layer)159 void ImageView::resolve(ImageView *resolveAttachment, int layer)
160 {
161 if((subresourceRange.levelCount != 1) || (resolveAttachment->subresourceRange.levelCount != 1))
162 {
163 UNIMPLEMENTED("b/148242443: levelCount != 1"); // FIXME(b/148242443)
164 }
165
166 VkImageCopy region;
167 region.srcSubresource = {
168 subresourceRange.aspectMask,
169 subresourceRange.baseMipLevel,
170 subresourceRange.baseArrayLayer + layer,
171 1
172 };
173 region.srcOffset = { 0, 0, 0 };
174 region.dstSubresource = {
175 resolveAttachment->subresourceRange.aspectMask,
176 resolveAttachment->subresourceRange.baseMipLevel,
177 resolveAttachment->subresourceRange.baseArrayLayer + layer,
178 1
179 };
180 region.dstOffset = { 0, 0, 0 };
181 region.extent = image->getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask),
182 subresourceRange.baseMipLevel);
183
184 image->copyTo(resolveAttachment->image, region);
185 }
186
resolve(ImageView * resolveAttachment)187 void ImageView::resolve(ImageView *resolveAttachment)
188 {
189 if((subresourceRange.levelCount != 1) || (resolveAttachment->subresourceRange.levelCount != 1))
190 {
191 UNIMPLEMENTED("b/148242443: levelCount != 1"); // FIXME(b/148242443)
192 }
193
194 VkImageCopy region;
195 region.srcSubresource = {
196 subresourceRange.aspectMask,
197 subresourceRange.baseMipLevel,
198 subresourceRange.baseArrayLayer,
199 subresourceRange.layerCount
200 };
201 region.srcOffset = { 0, 0, 0 };
202 region.dstSubresource = {
203 resolveAttachment->subresourceRange.aspectMask,
204 resolveAttachment->subresourceRange.baseMipLevel,
205 resolveAttachment->subresourceRange.baseArrayLayer,
206 resolveAttachment->subresourceRange.layerCount
207 };
208 region.dstOffset = { 0, 0, 0 };
209 region.extent = image->getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask),
210 subresourceRange.baseMipLevel);
211
212 image->copyTo(resolveAttachment->image, region);
213 }
214
resolveWithLayerMask(ImageView * resolveAttachment,uint32_t layerMask)215 void ImageView::resolveWithLayerMask(ImageView *resolveAttachment, uint32_t layerMask)
216 {
217 while(layerMask)
218 {
219 int layer = sw::log2i(layerMask);
220 layerMask &= ~(1 << layer);
221 resolve(resolveAttachment, layer);
222 }
223 }
224
getImage(Usage usage) const225 const Image *ImageView::getImage(Usage usage) const
226 {
227 switch(usage)
228 {
229 case RAW:
230 return image;
231 case SAMPLING:
232 return image->getSampledImage(format);
233 default:
234 UNREACHABLE("usage %d", int(usage));
235 return nullptr;
236 }
237 }
238
getFormat(Usage usage) const239 Format ImageView::getFormat(Usage usage) const
240 {
241 Format imageFormat = ((usage == RAW) || (getImage(usage) == image)) ? format : getImage(usage)->getFormat();
242 return imageFormat.getAspectFormat(subresourceRange.aspectMask);
243 }
244
rowPitchBytes(VkImageAspectFlagBits aspect,uint32_t mipLevel,Usage usage) const245 int ImageView::rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage) const
246 {
247 return getImage(usage)->rowPitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel);
248 }
249
slicePitchBytes(VkImageAspectFlagBits aspect,uint32_t mipLevel,Usage usage) const250 int ImageView::slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage) const
251 {
252 return getImage(usage)->slicePitchBytes(aspect, subresourceRange.baseMipLevel + mipLevel);
253 }
254
getMipLevelSize(VkImageAspectFlagBits aspect,uint32_t mipLevel,Usage usage) const255 int ImageView::getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage) const
256 {
257 return getImage(usage)->getMipLevelSize(aspect, subresourceRange.baseMipLevel + mipLevel);
258 }
259
layerPitchBytes(VkImageAspectFlagBits aspect,Usage usage) const260 int ImageView::layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage) const
261 {
262 return static_cast<int>(getImage(usage)->getLayerSize(aspect));
263 }
264
getMipLevelExtent(uint32_t mipLevel) const265 VkExtent3D ImageView::getMipLevelExtent(uint32_t mipLevel) const
266 {
267 return image->getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask),
268 subresourceRange.baseMipLevel + mipLevel);
269 }
270
getOffsetPointer(const VkOffset3D & offset,VkImageAspectFlagBits aspect,uint32_t mipLevel,uint32_t layer,Usage usage) const271 void *ImageView::getOffsetPointer(const VkOffset3D &offset, VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer, Usage usage) const
272 {
273 ASSERT(mipLevel < subresourceRange.levelCount);
274
275 VkImageSubresourceLayers imageSubresourceLayers = {
276 static_cast<VkImageAspectFlags>(aspect),
277 subresourceRange.baseMipLevel + mipLevel,
278 subresourceRange.baseArrayLayer + layer,
279 subresourceRange.layerCount
280 };
281
282 return getImage(usage)->getTexelPointer(offset, imageSubresourceLayers);
283 }
284
285 } // namespace vk
286