1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Image load/store Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktImageLoadStoreTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageLoadStoreUtil.hpp"
29 #include "vktImageTexture.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkImageUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 #include "vkBufferWithMemory.hpp"
44
45 #include "deMath.h"
46 #include "deUniquePtr.hpp"
47 #include "deSharedPtr.hpp"
48 #include "deStringUtil.hpp"
49
50 #include "tcuImageCompare.hpp"
51 #include "tcuTexture.hpp"
52 #include "tcuTextureUtil.hpp"
53 #include "tcuFloat.hpp"
54 #include "tcuFloatFormat.hpp"
55 #include "tcuStringTemplate.hpp"
56 #include "tcuVectorUtil.hpp"
57
58 #include <string>
59 #include <vector>
60 #include <map>
61
62 using namespace vk;
63
64 namespace vkt
65 {
66 namespace image
67 {
68 namespace
69 {
70
71 enum DeviceScopeType
72 {
73 DEVICESCOPE_NONE,
74 DEVICESCOPE_STORE,
75 DEVICESCOPE_LOAD
76 };
77
78 enum TestConfigurationType
79 {
80 TC_NONE,
81 TC_COMP_COMP,
82 TC_COMP_DRAW
83 };
84
85 // Check for three-component (non-packed) format, i.e. pixel size is a multiple of 3.
formatHasThreeComponents(VkFormat format)86 bool formatHasThreeComponents(VkFormat format)
87 {
88 const tcu::TextureFormat texFormat = mapVkFormat(format);
89 return (getPixelSize(texFormat) % 3) == 0;
90 }
91
getSingleComponentFormat(VkFormat format)92 VkFormat getSingleComponentFormat(VkFormat format)
93 {
94 tcu::TextureFormat texFormat = mapVkFormat(format);
95 texFormat = tcu::TextureFormat(tcu::TextureFormat::R, texFormat.type);
96 return mapTextureFormat(texFormat);
97 }
98
getImageAspect(VkFormat format)99 VkImageAspectFlags getImageAspect(VkFormat format)
100 {
101 return isDepthStencilFormat(format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
102 }
103
makeBufferImageCopy(const Texture & texture)104 inline VkBufferImageCopy makeBufferImageCopy(const Texture &texture)
105 {
106 return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
107 }
108
makeBufferImageCopy(const Texture & texture,const VkImageAspectFlags & aspect)109 VkBufferImageCopy makeBufferImageCopy(const Texture &texture, const VkImageAspectFlags &aspect)
110 {
111 const VkBufferImageCopy copyParams = {
112 0ull, // VkDeviceSize bufferOffset;
113 0u, // uint32_t bufferRowLength;
114 0u, // uint32_t bufferImageHeight;
115 makeImageSubresourceLayers(aspect, 0u, 0u, texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
116 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
117 makeExtent3D(texture.layerSize()), // VkExtent3D imageExtent;
118 };
119 return copyParams;
120 }
121
getShaderImageFormatQualifierStr(const VkFormat & format)122 std::string getShaderImageFormatQualifierStr(const VkFormat &format)
123 {
124 VkFormat testFormat;
125 switch (format)
126 {
127 case VK_FORMAT_D16_UNORM:
128 testFormat = VK_FORMAT_R16_UNORM;
129 break;
130 case VK_FORMAT_D32_SFLOAT:
131 testFormat = VK_FORMAT_R32_SFLOAT;
132 break;
133 default:
134 testFormat = format;
135 }
136 return getShaderImageFormatQualifier(mapVkFormat(testFormat));
137 }
138
getLayerOrSlice(const Texture & texture,const tcu::ConstPixelBufferAccess access,const int layer)139 tcu::ConstPixelBufferAccess getLayerOrSlice(const Texture &texture, const tcu::ConstPixelBufferAccess access,
140 const int layer)
141 {
142 switch (texture.type())
143 {
144 case IMAGE_TYPE_1D:
145 case IMAGE_TYPE_2D:
146 case IMAGE_TYPE_BUFFER:
147 // Not layered
148 DE_ASSERT(layer == 0);
149 return access;
150
151 case IMAGE_TYPE_1D_ARRAY:
152 return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
153
154 case IMAGE_TYPE_2D_ARRAY:
155 case IMAGE_TYPE_CUBE:
156 case IMAGE_TYPE_CUBE_ARRAY:
157 case IMAGE_TYPE_3D: // 3d texture is treated as if depth was the layers
158 return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
159
160 default:
161 DE_FATAL("Internal test error");
162 return tcu::ConstPixelBufferAccess();
163 }
164 }
165
166 //! \return the size in bytes of a given level of a mipmap image, including array layers.
getMipmapLevelImageSizeBytes(const Texture & texture,const vk::VkFormat format,const uint32_t mipmapLevel)167 vk::VkDeviceSize getMipmapLevelImageSizeBytes(const Texture &texture, const vk::VkFormat format,
168 const uint32_t mipmapLevel)
169 {
170 tcu::IVec3 size = texture.size(mipmapLevel);
171 return tcu::getPixelSize(vk::mapVkFormat(format)) * size.x() * size.y() * size.z();
172 }
173
174 //! \return the size in bytes of the whole mipmap image, including all mipmap levels and array layers
getMipmapImageTotalSizeBytes(const Texture & texture,const vk::VkFormat format)175 vk::VkDeviceSize getMipmapImageTotalSizeBytes(const Texture &texture, const vk::VkFormat format)
176 {
177 vk::VkDeviceSize size = 0u;
178 int32_t levelCount = 0u;
179
180 do
181 {
182 size += getMipmapLevelImageSizeBytes(texture, format, levelCount);
183 levelCount++;
184 } while (levelCount < texture.numMipmapLevels());
185 return size;
186 }
187
188 //! \return true if all layers match in both pixel buffers
comparePixelBuffers(tcu::TestLog & log,const Texture & texture,const VkFormat format,const tcu::ConstPixelBufferAccess reference,const tcu::ConstPixelBufferAccess result,const uint32_t mipmapLevel=0u)189 bool comparePixelBuffers(tcu::TestLog &log, const Texture &texture, const VkFormat format,
190 const tcu::ConstPixelBufferAccess reference, const tcu::ConstPixelBufferAccess result,
191 const uint32_t mipmapLevel = 0u)
192 {
193 DE_ASSERT(reference.getFormat() == result.getFormat());
194 DE_ASSERT(reference.getSize() == result.getSize());
195
196 const bool is3d = (texture.type() == IMAGE_TYPE_3D);
197 const int numLayersOrSlices = (is3d ? texture.size(mipmapLevel).z() : texture.numLayers());
198 const int numCubeFaces = 6;
199
200 int passedLayers = 0;
201 for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
202 {
203 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
204 const std::string comparisonDesc =
205 "Image Comparison, " + (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " +
206 de::toString(layerNdx / numCubeFaces) :
207 is3d ? "slice " + de::toString(layerNdx) :
208 "layer " + de::toString(layerNdx) + " , level " + de::toString(mipmapLevel));
209
210 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
211 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
212
213 bool ok = false;
214
215 switch (tcu::getTextureChannelClass(mapVkFormat(format).type))
216 {
217 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
218 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
219 {
220 ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer,
221 tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
222 break;
223 }
224
225 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
226 {
227 // Allow error of minimum representable difference
228 tcu::Vec4 threshold(
229 1.0f /
230 ((tcu::UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<uint32_t>()) - 1u)
231 .cast<float>());
232
233 // Add 1 ULP of fp32 imprecision to account for image comparison fp32 math with unorm->float conversions.
234 threshold += tcu::Vec4(std::numeric_limits<float>::epsilon());
235
236 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer,
237 threshold, tcu::COMPARE_LOG_RESULT);
238 break;
239 }
240
241 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
242 {
243 const tcu::UVec4 bitDepth =
244 tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<uint32_t>() - 1u;
245 // To avoid bit-shifting with negative value, which is undefined behaviour.
246 const tcu::UVec4 fixedBitDepth =
247 tcu::select(bitDepth, tcu::UVec4(0u, 0u, 0u, 0u),
248 tcu::greaterThanEqual(bitDepth.cast<int32_t>(), tcu::IVec4(0, 0, 0, 0)));
249
250 // Allow error of minimum representable difference
251 const tcu::Vec4 threshold(1.0f / ((tcu::UVec4(1u) << fixedBitDepth) - 1u).cast<float>());
252
253 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer,
254 threshold, tcu::COMPARE_LOG_RESULT);
255 break;
256 }
257
258 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
259 {
260 // Convert target format ulps to float ulps and allow 1 ulp difference
261 const tcu::UVec4 threshold(
262 tcu::UVec4(1u) << (tcu::UVec4(23) -
263 tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<uint32_t>()));
264
265 ok = tcu::floatUlpThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer,
266 resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
267 break;
268 }
269
270 default:
271 DE_FATAL("Unknown channel class");
272 }
273
274 if (ok)
275 ++passedLayers;
276 }
277
278 return passedLayers == numLayersOrSlices;
279 }
280
281 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
replaceBadFloatReinterpretValues(const tcu::PixelBufferAccess access)282 void replaceBadFloatReinterpretValues(const tcu::PixelBufferAccess access)
283 {
284 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
285
286 for (int z = 0; z < access.getDepth(); ++z)
287 for (int y = 0; y < access.getHeight(); ++y)
288 for (int x = 0; x < access.getWidth(); ++x)
289 {
290 const tcu::Vec4 color(access.getPixel(x, y, z));
291 tcu::Vec4 newColor = color;
292
293 for (int i = 0; i < 4; ++i)
294 {
295 if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
296 {
297 const tcu::Float16 f(color[i]);
298 if (f.isDenorm() || f.isInf() || f.isNaN())
299 newColor[i] = 0.0f;
300 }
301 else
302 {
303 const tcu::Float32 f(color[i]);
304 if (f.isDenorm() || f.isInf() || f.isNaN())
305 newColor[i] = 0.0f;
306 }
307 }
308
309 if (newColor != color)
310 access.setPixel(newColor, x, y, z);
311 }
312 }
313
314 //!< replace invalid pixels in the image (-128)
replaceSnormReinterpretValues(const tcu::PixelBufferAccess access)315 void replaceSnormReinterpretValues(const tcu::PixelBufferAccess access)
316 {
317 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
318
319 for (int z = 0; z < access.getDepth(); ++z)
320 for (int y = 0; y < access.getHeight(); ++y)
321 for (int x = 0; x < access.getWidth(); ++x)
322 {
323 const tcu::IVec4 color(access.getPixelInt(x, y, z));
324 tcu::IVec4 newColor = color;
325
326 for (int i = 0; i < 4; ++i)
327 {
328 const int32_t oldColor(color[i]);
329 if (oldColor == -128)
330 newColor[i] = -127;
331 }
332
333 if (newColor != color)
334 access.setPixel(newColor, x, y, z);
335 }
336 }
337
getMiddleValue(VkFormat imageFormat)338 tcu::Vec4 getMiddleValue(VkFormat imageFormat)
339 {
340 tcu::TextureFormat format = mapVkFormat(imageFormat);
341 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(format);
342 tcu::Vec4 val = (fmtInfo.valueMax - fmtInfo.valueMin) * tcu::Vec4(0.5f);
343
344 if (isIntegerFormat(imageFormat))
345 val = floor(val);
346
347 return val;
348 }
349
generateReferenceImage(const tcu::IVec3 & imageSize,const VkFormat imageFormat,const VkFormat readFormat,bool constantValue=false)350 tcu::TextureLevel generateReferenceImage(const tcu::IVec3 &imageSize, const VkFormat imageFormat,
351 const VkFormat readFormat, bool constantValue = false)
352 {
353 // Generate a reference image data using the storage format
354
355 tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
356 const tcu::PixelBufferAccess access = reference.getAccess();
357
358 const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
359 const float storeColorBias = computeStoreColorBias(imageFormat);
360
361 const bool srgbFormat = isSrgbFormat(imageFormat);
362 const bool intFormat = isIntegerFormat(imageFormat);
363 const bool storeNegativeValues = isSignedFormat(imageFormat) && (storeColorBias == 0);
364 const int xMax = imageSize.x() - 1;
365 const int yMax = imageSize.y() - 1;
366
367 for (int z = 0; z < imageSize.z(); ++z)
368 for (int y = 0; y < imageSize.y(); ++y)
369 for (int x = 0; x < imageSize.x(); ++x)
370 {
371 if (constantValue)
372 {
373 access.setPixel(getMiddleValue(imageFormat), x, y, z);
374 }
375 else
376 {
377 tcu::IVec4 color =
378 tcu::IVec4(x ^ y ^ z, (xMax - x) ^ y ^ z, x ^ (yMax - y) ^ z, (xMax - x) ^ (yMax - y) ^ z);
379
380 if (storeNegativeValues)
381 color -= tcu::IVec4(deRoundFloatToInt32((float)de::max(xMax, yMax) / 2.0f));
382
383 if (intFormat)
384 access.setPixel(color, x, y, z);
385 else
386 {
387 if (srgbFormat)
388 access.setPixel(tcu::linearToSRGB(color.asFloat() * storeColorScale + storeColorBias), x, y,
389 z);
390 else
391 access.setPixel(color.asFloat() * storeColorScale + storeColorBias, x, y, z);
392 }
393 }
394 }
395
396 // If the image is to be accessed as a float texture, get rid of invalid values
397
398 if (isFloatFormat(readFormat) && imageFormat != readFormat)
399 replaceBadFloatReinterpretValues(
400 tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
401 if (isSnormFormat(readFormat) && imageFormat != readFormat)
402 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
403
404 return reference;
405 }
406
generateReferenceImage(const tcu::IVec3 & imageSize,const VkFormat imageFormat,bool constantValue=false)407 inline tcu::TextureLevel generateReferenceImage(const tcu::IVec3 &imageSize, const VkFormat imageFormat,
408 bool constantValue = false)
409 {
410 return generateReferenceImage(imageSize, imageFormat, imageFormat, constantValue);
411 }
412
flipHorizontally(const tcu::PixelBufferAccess access)413 void flipHorizontally(const tcu::PixelBufferAccess access)
414 {
415 const int xMax = access.getWidth() - 1;
416 const int halfWidth = access.getWidth() / 2;
417
418 if (isIntegerFormat(mapTextureFormat(access.getFormat())))
419 for (int z = 0; z < access.getDepth(); z++)
420 for (int y = 0; y < access.getHeight(); y++)
421 for (int x = 0; x < halfWidth; x++)
422 {
423 const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
424 access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
425 access.setPixel(temp, x, y, z);
426 }
427 else
428 for (int z = 0; z < access.getDepth(); z++)
429 for (int y = 0; y < access.getHeight(); y++)
430 for (int x = 0; x < halfWidth; x++)
431 {
432 const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
433 access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
434 access.setPixel(temp, x, y, z);
435 }
436 }
437
formatsAreCompatible(const VkFormat format0,const VkFormat format1)438 inline bool formatsAreCompatible(const VkFormat format0, const VkFormat format1)
439 {
440 const bool isAlphaOnly = (isAlphaOnlyFormat(format0) || isAlphaOnlyFormat(format1));
441 return format0 == format1 ||
442 (mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize() && !isAlphaOnly);
443 }
444
commandImageWriteBarrierBetweenShaderInvocations(Context & context,const VkCommandBuffer cmdBuffer,const VkImage image,const Texture & texture,VkImageAspectFlags aspectMask=VK_IMAGE_ASPECT_COLOR_BIT)445 void commandImageWriteBarrierBetweenShaderInvocations(Context &context, const VkCommandBuffer cmdBuffer,
446 const VkImage image, const Texture &texture,
447 VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT)
448 {
449 const DeviceInterface &vk = context.getDeviceInterface();
450
451 const VkImageSubresourceRange fullImageSubresourceRange =
452 makeImageSubresourceRange(aspectMask, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
453 const VkImageMemoryBarrier shaderWriteBarrier =
454 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, 0u, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, image,
455 fullImageSubresourceRange);
456
457 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
458 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &shaderWriteBarrier);
459 }
460
commandBufferWriteBarrierBeforeHostRead(Context & context,const VkCommandBuffer cmdBuffer,const VkBuffer buffer,const VkDeviceSize bufferSizeBytes)461 void commandBufferWriteBarrierBeforeHostRead(Context &context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer,
462 const VkDeviceSize bufferSizeBytes)
463 {
464 const DeviceInterface &vk = context.getDeviceInterface();
465
466 const VkBufferMemoryBarrier shaderWriteBarrier =
467 makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, buffer, 0ull, bufferSizeBytes);
468
469 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
470 (VkDependencyFlags)0, 0, nullptr, 1, &shaderWriteBarrier, 0, nullptr);
471 }
472
473 //! Copy all layers of an image to a buffer.
commandCopyImageToBuffer(Context & context,const VkCommandBuffer cmdBuffer,const VkImage image,const VkBuffer buffer,const VkDeviceSize bufferSizeBytes,const Texture & texture,VkImageAspectFlags aspectMask=VK_IMAGE_ASPECT_COLOR_BIT)474 void commandCopyImageToBuffer(Context &context, const VkCommandBuffer cmdBuffer, const VkImage image,
475 const VkBuffer buffer, const VkDeviceSize bufferSizeBytes, const Texture &texture,
476 VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT)
477 {
478 const DeviceInterface &vk = context.getDeviceInterface();
479
480 const VkImageSubresourceRange fullImageSubresourceRange =
481 makeImageSubresourceRange(aspectMask, 0u, 1u, 0u, texture.numLayers());
482 const VkImageMemoryBarrier prepareForTransferBarrier =
483 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
484 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, fullImageSubresourceRange);
485
486 const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture, aspectMask);
487
488 const VkBufferMemoryBarrier copyBarrier =
489 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, buffer, 0ull, bufferSizeBytes);
490
491 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
492 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &prepareForTransferBarrier);
493 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ©Region);
494 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
495 0, nullptr, 1, ©Barrier, 0, nullptr);
496 }
497
498 //! Copy all layers of a mipmap image to a buffer.
commandCopyMipmapImageToBuffer(Context & context,const VkCommandBuffer cmdBuffer,const VkImage image,const VkFormat imageFormat,const VkBuffer buffer,const VkDeviceSize bufferSizeBytes,const Texture & texture)499 void commandCopyMipmapImageToBuffer(Context &context, const VkCommandBuffer cmdBuffer, const VkImage image,
500 const VkFormat imageFormat, const VkBuffer buffer,
501 const VkDeviceSize bufferSizeBytes, const Texture &texture)
502 {
503 const DeviceInterface &vk = context.getDeviceInterface();
504
505 const VkImageSubresourceRange fullImageSubresourceRange =
506 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
507 const VkImageMemoryBarrier prepareForTransferBarrier =
508 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
509 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, fullImageSubresourceRange);
510
511 std::vector<VkBufferImageCopy> copyRegions;
512 VkDeviceSize bufferOffset = 0u;
513 for (int32_t levelNdx = 0; levelNdx < texture.numMipmapLevels(); levelNdx++)
514 {
515 const VkBufferImageCopy copyParams = {
516 bufferOffset, // VkDeviceSize bufferOffset;
517 0u, // uint32_t bufferRowLength;
518 0u, // uint32_t bufferImageHeight;
519 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u,
520 texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
521 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
522 makeExtent3D(texture.layerSize(levelNdx)), // VkExtent3D imageExtent;
523 };
524 copyRegions.push_back(copyParams);
525 bufferOffset += getMipmapLevelImageSizeBytes(texture, imageFormat, levelNdx);
526 }
527
528 const VkBufferMemoryBarrier copyBarrier =
529 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, buffer, 0ull, bufferSizeBytes);
530
531 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
532 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &prepareForTransferBarrier);
533 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer,
534 (uint32_t)copyRegions.size(), copyRegions.data());
535 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
536 0, nullptr, 1, ©Barrier, 0, nullptr);
537 }
538
539 class StoreTest : public TestCase
540 {
541 public:
542 enum TestFlags
543 {
544 FLAG_SINGLE_LAYER_BIND = 0x1, //!< Run the shader multiple times, each time binding a different layer.
545 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 0x2, //!< Declare the format of the images in the shader code
546 FLAG_MINALIGN = 0x4, //!< Use bufferview offset that matches the advertised minimum alignment
547 FLAG_STORE_CONSTANT_VALUE = 0x8, //!< Store constant value
548 };
549
550 StoreTest(tcu::TestContext &testCtx, const std::string &name, const Texture &texture, const VkFormat format,
551 const VkImageTiling tiling, const uint32_t flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
552
553 virtual void checkSupport(Context &context) const;
554 void initPrograms(SourceCollections &programCollection) const;
555 TestInstance *createInstance(Context &context) const;
556
557 private:
558 const Texture m_texture;
559 const VkFormat m_format;
560 const VkImageTiling m_tiling;
561 const bool m_declareImageFormatInShader;
562 const bool m_singleLayerBind;
563 const bool m_minalign;
564 const bool m_storeConstantValue;
565 };
566
StoreTest(tcu::TestContext & testCtx,const std::string & name,const Texture & texture,const VkFormat format,const VkImageTiling tiling,const uint32_t flags)567 StoreTest::StoreTest(tcu::TestContext &testCtx, const std::string &name, const Texture &texture, const VkFormat format,
568 const VkImageTiling tiling, const uint32_t flags)
569 : TestCase(testCtx, name)
570 , m_texture(texture)
571 , m_format(format)
572 , m_tiling(tiling)
573 , m_declareImageFormatInShader((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
574 , m_singleLayerBind((flags & FLAG_SINGLE_LAYER_BIND) != 0)
575 , m_minalign((flags & FLAG_MINALIGN) != 0)
576 , m_storeConstantValue((flags & FLAG_STORE_CONSTANT_VALUE) != 0)
577 {
578 if (m_singleLayerBind)
579 DE_ASSERT(m_texture.numLayers() > 1);
580 }
581
checkSupport(Context & context) const582 void StoreTest::checkSupport(Context &context) const
583 {
584 #ifndef CTS_USES_VULKANSC
585 if (m_format == VK_FORMAT_A8_UNORM_KHR || m_format == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
586 context.requireDeviceFunctionality("VK_KHR_maintenance5");
587
588 const VkFormatProperties3 formatProperties(context.getFormatProperties(m_format));
589
590 const auto &tilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? formatProperties.optimalTilingFeatures :
591 formatProperties.linearTilingFeatures;
592
593 if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !m_declareImageFormatInShader &&
594 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
595 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage buffer");
596
597 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !m_declareImageFormatInShader &&
598 !(tilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
599 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage images");
600
601 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
602 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
603
604 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(tilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
605 TCU_THROW(NotSupportedError, "Format not supported for storage images");
606
607 if (m_texture.type() == IMAGE_TYPE_BUFFER &&
608 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
609 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
610 #else
611 const VkFormatProperties formatProperties(
612 getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_format));
613 const auto tilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? formatProperties.optimalTilingFeatures :
614 formatProperties.linearTilingFeatures;
615
616 if (!m_declareImageFormatInShader)
617 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
618
619 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
620 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
621
622 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(tilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
623 TCU_THROW(NotSupportedError, "Format not supported for storage images");
624
625 if (m_texture.type() == IMAGE_TYPE_BUFFER &&
626 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
627 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
628 #endif // CTS_USES_VULKANSC
629
630 const auto &vki = context.getInstanceInterface();
631 const auto physicalDevice = context.getPhysicalDevice();
632
633 VkImageFormatProperties imageFormatProperties;
634 const auto result = vki.getPhysicalDeviceImageFormatProperties(
635 physicalDevice, m_format, mapImageType(m_texture.type()), m_tiling,
636 (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0, &imageFormatProperties);
637
638 if (result != VK_SUCCESS)
639 {
640 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
641 TCU_THROW(NotSupportedError, "Format unsupported for tiling");
642 else
643 TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned unexpected error");
644 }
645
646 if (imageFormatProperties.maxArrayLayers < (uint32_t)m_texture.numLayers())
647 {
648 TCU_THROW(NotSupportedError, "This format and tiling combination does not support this number of aray layers");
649 }
650
651 if (imageFormatProperties.maxMipLevels < (uint32_t)m_texture.numMipmapLevels())
652 {
653 TCU_THROW(NotSupportedError, "This format and tiling combination does not support this number of miplevels");
654 }
655 }
656
initPrograms(SourceCollections & programCollection) const657 void StoreTest::initPrograms(SourceCollections &programCollection) const
658 {
659 const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
660 const float storeColorBias = computeStoreColorBias(m_format);
661 DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
662
663 const uint32_t xMax = m_texture.size().x() - 1;
664 const uint32_t yMax = m_texture.size().y() - 1;
665 const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
666 const bool storeNegativeValues = isSignedFormat(m_format) && (storeColorBias == 0);
667 bool useClamp = false;
668 const std::string colorType = signednessPrefix + "vec4";
669 std::string colorBaseExpr = colorType + "(";
670
671 std::string colorExpr;
672
673 if (m_storeConstantValue)
674 {
675 tcu::Vec4 val = getMiddleValue(m_format);
676
677 if (isIntegerFormat(m_format))
678 {
679 colorExpr = colorBaseExpr + de::toString(static_cast<int64_t>(val.x())) + ", " +
680 de::toString(static_cast<int64_t>(val.y())) + ", " +
681 de::toString(static_cast<int64_t>(val.z())) + ", " +
682 de::toString(static_cast<int64_t>(val.w())) + ")";
683 }
684 else
685 {
686 colorExpr = colorBaseExpr + de::toString(val.x()) + ", " + de::toString(val.y()) + ", " +
687 de::toString(val.z()) + ", " + de::toString(val.w()) + ")";
688 }
689 }
690 else
691 {
692 colorBaseExpr = colorBaseExpr + "gx^gy^gz, " + "(" + de::toString(xMax) + "-gx)^gy^gz, " + "gx^(" +
693 de::toString(yMax) + "-gy)^gz, " + "(" + de::toString(xMax) + "-gx)^(" + de::toString(yMax) +
694 "-gy)^gz)";
695
696 // Large integer values may not be represented with formats with low bit depths
697 if (isIntegerFormat(m_format))
698 {
699 const int64_t minStoreValue =
700 storeNegativeValues ? 0 - deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : 0;
701 const int64_t maxStoreValue =
702 storeNegativeValues ? deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : de::max(xMax, yMax);
703
704 useClamp = !isRepresentableIntegerValue(tcu::Vector<int64_t, 4>(minStoreValue), mapVkFormat(m_format)) ||
705 !isRepresentableIntegerValue(tcu::Vector<int64_t, 4>(maxStoreValue), mapVkFormat(m_format));
706 }
707
708 // Clamp if integer value cannot be represented with the current format
709 if (useClamp)
710 {
711 const tcu::IVec4 bitDepths = tcu::getTextureFormatBitDepth(mapVkFormat(m_format));
712 tcu::IVec4 minRepresentableValue;
713 tcu::IVec4 maxRepresentableValue;
714
715 switch (tcu::getTextureChannelClass(mapVkFormat(m_format).type))
716 {
717 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
718 {
719 minRepresentableValue = tcu::IVec4(0);
720 maxRepresentableValue = (tcu::IVec4(1) << bitDepths) - tcu::IVec4(1);
721 break;
722 }
723
724 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
725 {
726 minRepresentableValue = -(tcu::IVec4(1) << bitDepths - tcu::IVec4(1));
727 maxRepresentableValue = (tcu::IVec4(1) << (bitDepths - tcu::IVec4(1))) - tcu::IVec4(1);
728 break;
729 }
730
731 default:
732 DE_ASSERT(isIntegerFormat(m_format));
733 }
734
735 colorBaseExpr = "clamp(" + colorBaseExpr + ", " + signednessPrefix + "vec4" +
736 de::toString(minRepresentableValue) + ", " + signednessPrefix + "vec4" +
737 de::toString(maxRepresentableValue) + ")";
738 }
739
740 colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale)) +
741 (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
742
743 if (storeNegativeValues)
744 colorExpr += "-" + de::toString(deRoundFloatToInt32((float)deMax32(xMax, yMax) / 2.0f));
745 }
746
747 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
748 const std::string texelCoordStr = (dimension == 1 ? "gx" :
749 dimension == 2 ? "ivec2(gx, gy)" :
750 dimension == 3 ? "ivec3(gx, gy, gz)" :
751 "");
752
753 const ImageType usedImageType =
754 (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
755 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
756
757 std::string maybeFmtQualStr = m_declareImageFormatInShader ? ", " + getShaderImageFormatQualifierStr(m_format) : "";
758
759 std::ostringstream src;
760 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
761 << "\n"
762 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
763 << "layout (binding = 0" << maybeFmtQualStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
764
765 if (m_singleLayerBind)
766 src << "layout (binding = 1) readonly uniform Constants {\n"
767 << " int u_layerNdx;\n"
768 << "};\n";
769
770 src << "\n"
771 << "void main (void)\n"
772 << "{\n"
773 << " int gx = int(gl_GlobalInvocationID.x);\n"
774 << " int gy = int(gl_GlobalInvocationID.y);\n"
775 << " int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
776 << " " << colorType << " storedColor = " << colorExpr << ";\n"
777 << " imageStore(u_image, " << texelCoordStr << ", storedColor);\n"
778 << "}\n";
779
780 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
781 }
782
783 //! Generic test iteration algorithm for image tests
784 class BaseTestInstance : public TestInstance
785 {
786 public:
787 BaseTestInstance(Context &context, const Texture &texture, const VkFormat format,
788 const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign,
789 const bool bufferLoadUniform);
790
791 virtual tcu::TestStatus iterate(void);
792
~BaseTestInstance(void)793 virtual ~BaseTestInstance(void)
794 {
795 }
796
797 protected:
798 virtual VkDescriptorSetLayout prepareDescriptors(void) = 0;
799 virtual tcu::TestStatus verifyResult(void) = 0;
800
801 virtual void commandBeforeCompute(const VkCommandBuffer cmdBuffer) = 0;
802 virtual void commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer) = 0;
803 virtual void commandAfterCompute(const VkCommandBuffer cmdBuffer) = 0;
804
805 virtual void commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout,
806 const int layerNdx) = 0;
807 virtual uint32_t getViewOffset(Context &context, const VkFormat format, bool uniform);
808
809 const Texture m_texture;
810 const VkFormat m_format;
811 const bool m_declareImageFormatInShader;
812 const bool m_singleLayerBind;
813 const bool m_minalign;
814 const bool m_bufferLoadUniform;
815 const uint32_t m_srcViewOffset;
816 const uint32_t m_dstViewOffset;
817 };
818
BaseTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool bufferLoadUniform)819 BaseTestInstance::BaseTestInstance(Context &context, const Texture &texture, const VkFormat format,
820 const bool declareImageFormatInShader, const bool singleLayerBind,
821 const bool minalign, const bool bufferLoadUniform)
822 : TestInstance(context)
823 , m_texture(texture)
824 , m_format(format)
825 , m_declareImageFormatInShader(declareImageFormatInShader)
826 , m_singleLayerBind(singleLayerBind)
827 , m_minalign(minalign)
828 , m_bufferLoadUniform(bufferLoadUniform)
829 , m_srcViewOffset(getViewOffset(context, format, m_bufferLoadUniform))
830 , m_dstViewOffset(
831 getViewOffset(context, formatHasThreeComponents(format) ? getSingleComponentFormat(format) : format, false))
832 {
833 }
834
iterate(void)835 tcu::TestStatus BaseTestInstance::iterate(void)
836 {
837 const DeviceInterface &vk = m_context.getDeviceInterface();
838 const VkDevice device = m_context.getDevice();
839 const VkQueue queue = m_context.getUniversalQueue();
840 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
841
842 const Unique<VkShaderModule> shaderModule(
843 createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
844
845 const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
846 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
847 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
848
849 const Unique<VkCommandPool> cmdPool(
850 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
851 const Unique<VkCommandBuffer> cmdBuffer(
852 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
853
854 beginCommandBuffer(vk, *cmdBuffer);
855
856 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
857 commandBeforeCompute(*cmdBuffer);
858
859 const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
860 const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
861 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
862 {
863 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
864
865 if (layerNdx > 0)
866 commandBetweenShaderInvocations(*cmdBuffer);
867
868 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
869 }
870
871 commandAfterCompute(*cmdBuffer);
872
873 endCommandBuffer(vk, *cmdBuffer);
874
875 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
876
877 return verifyResult();
878 }
879
880 //! Base store test implementation
881 class StoreTestInstance : public BaseTestInstance
882 {
883 public:
884 StoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
885 const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign,
886 const bool storeConstantValue);
887
888 protected:
889 virtual tcu::TestStatus verifyResult(void);
890
891 // Add empty implementations for functions that might be not needed
commandBeforeCompute(const VkCommandBuffer)892 void commandBeforeCompute(const VkCommandBuffer)
893 {
894 }
commandBetweenShaderInvocations(const VkCommandBuffer)895 void commandBetweenShaderInvocations(const VkCommandBuffer)
896 {
897 }
commandAfterCompute(const VkCommandBuffer)898 void commandAfterCompute(const VkCommandBuffer)
899 {
900 }
901
902 de::MovePtr<BufferWithMemory> m_imageBuffer;
903 const VkDeviceSize m_imageSizeBytes;
904 bool m_storeConstantValue;
905 };
906
getViewOffset(Context & context,const VkFormat format,bool uniform)907 uint32_t BaseTestInstance::getViewOffset(Context &context, const VkFormat format, bool uniform)
908 {
909 if (m_minalign)
910 {
911 if (!context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
912 return (uint32_t)context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
913
914 VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties;
915 deMemset(&alignmentProperties, 0, sizeof(alignmentProperties));
916 alignmentProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
917
918 VkPhysicalDeviceProperties2 properties2;
919 deMemset(&properties2, 0, sizeof(properties2));
920 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
921 properties2.pNext = &alignmentProperties;
922
923 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
924
925 VkBool32 singleTexelAlignment = uniform ? alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
926 alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
927 VkDeviceSize align = uniform ? alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
928 alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
929
930 VkDeviceSize texelSize = formatHasThreeComponents(format) ? tcu::getChannelSize(vk::mapVkFormat(format).type) :
931 tcu::getPixelSize(vk::mapVkFormat(format));
932
933 if (singleTexelAlignment)
934 align = de::min(align, texelSize);
935
936 return (uint32_t)align;
937 }
938
939 return 0;
940 }
941
StoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool storeConstantValue)942 StoreTestInstance::StoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
943 const bool declareImageFormatInShader, const bool singleLayerBind,
944 const bool minalign, const bool storeConstantValue)
945 : BaseTestInstance(context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, false)
946 , m_imageSizeBytes(getImageSizeBytes(texture.size(), format))
947 , m_storeConstantValue(storeConstantValue)
948 {
949 const DeviceInterface &vk = m_context.getDeviceInterface();
950 const VkDevice device = m_context.getDevice();
951 Allocator &allocator = m_context.getDefaultAllocator();
952
953 // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
954
955 m_imageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
956 vk, device, allocator,
957 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset,
958 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
959 MemoryRequirement::HostVisible));
960 }
961
verifyResult(void)962 tcu::TestStatus StoreTestInstance::verifyResult(void)
963 {
964 const DeviceInterface &vk = m_context.getDeviceInterface();
965 const VkDevice device = m_context.getDevice();
966
967 const tcu::IVec3 imageSize = m_texture.size();
968 const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format, m_storeConstantValue);
969
970 const Allocation &alloc = m_imageBuffer->getAllocation();
971 invalidateAlloc(vk, device, alloc);
972 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize,
973 (const char *)alloc.getHostPtr() + m_dstViewOffset);
974
975 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
976 return tcu::TestStatus::pass("Passed");
977 else
978 return tcu::TestStatus::fail("Image comparison failed");
979 }
980
981 //! Store test for images
982 class ImageStoreTestInstance : public StoreTestInstance
983 {
984 public:
985 ImageStoreTestInstance(Context &context, const Texture &texture, const VkFormat format, const VkImageTiling tiling,
986 const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign,
987 const bool storeConstantValue);
988
989 protected:
990 VkDescriptorSetLayout prepareDescriptors(void);
991 void commandBeforeCompute(const VkCommandBuffer cmdBuffer);
992 void commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer);
993 void commandAfterCompute(const VkCommandBuffer cmdBuffer);
994
995 void commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout,
996 const int layerNdx);
997
998 de::MovePtr<Image> m_image;
999 de::MovePtr<BufferWithMemory> m_constantsBuffer;
1000 const VkDeviceSize m_constantsBufferChunkSizeBytes;
1001 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1002 Move<VkDescriptorPool> m_descriptorPool;
1003 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1004 std::vector<SharedVkImageView> m_allImageViews;
1005 };
1006
ImageStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkImageTiling tiling,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool storeConstantValue)1007 ImageStoreTestInstance::ImageStoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
1008 const VkImageTiling tiling, const bool declareImageFormatInShader,
1009 const bool singleLayerBind, const bool minalign,
1010 const bool storeConstantValue)
1011 : StoreTestInstance(context, texture, format, declareImageFormatInShader, singleLayerBind, minalign,
1012 storeConstantValue)
1013 , m_constantsBufferChunkSizeBytes(getOptimalUniformBufferChunkSize(context.getInstanceInterface(),
1014 context.getPhysicalDevice(), sizeof(uint32_t)))
1015 , m_allDescriptorSets(texture.numLayers())
1016 , m_allImageViews(texture.numLayers())
1017 {
1018 const DeviceInterface &vk = m_context.getDeviceInterface();
1019 const VkDevice device = m_context.getDevice();
1020 Allocator &allocator = m_context.getDefaultAllocator();
1021
1022 m_image = de::MovePtr<Image>(
1023 new Image(vk, device, allocator,
1024 makeImageCreateInfo(m_texture, m_format,
1025 (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0u, tiling),
1026 MemoryRequirement::Any));
1027
1028 // This buffer will be used to pass constants to the shader
1029
1030 const int numLayers = m_texture.numLayers();
1031 const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
1032 m_constantsBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1033 vk, device, allocator, makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
1034 MemoryRequirement::HostVisible));
1035
1036 {
1037 const Allocation &alloc = m_constantsBuffer->getAllocation();
1038 uint8_t *const basePtr = static_cast<uint8_t *>(alloc.getHostPtr());
1039
1040 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
1041
1042 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1043 {
1044 uint32_t *valuePtr = reinterpret_cast<uint32_t *>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
1045 *valuePtr = static_cast<uint32_t>(layerNdx);
1046 }
1047
1048 flushAlloc(vk, device, alloc);
1049 }
1050 }
1051
prepareDescriptors(void)1052 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors(void)
1053 {
1054 const DeviceInterface &vk = m_context.getDeviceInterface();
1055 const VkDevice device = m_context.getDevice();
1056
1057 const int numLayers = m_texture.numLayers();
1058 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1059 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1060 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1061 .build(vk, device);
1062
1063 m_descriptorPool = DescriptorPoolBuilder()
1064 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1065 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
1066 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1067
1068 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
1069
1070 if (m_singleLayerBind)
1071 {
1072 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1073 {
1074 m_allDescriptorSets[layerNdx] =
1075 makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1076 m_allImageViews[layerNdx] = makeVkSharedPtr(makeImageView(
1077 vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
1078 makeImageSubresourceRange(aspectMask, 0u, 1u, layerNdx, 1u)));
1079 }
1080 }
1081 else // bind all layers at once
1082 {
1083 m_allDescriptorSets[0] =
1084 makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1085 m_allImageViews[0] =
1086 makeVkSharedPtr(makeImageView(vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
1087 makeImageSubresourceRange(aspectMask, 0u, 1u, 0u, numLayers)));
1088 }
1089
1090 return *m_descriptorSetLayout; // not passing the ownership
1091 }
1092
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)1093 void ImageStoreTestInstance::commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,
1094 const VkPipelineLayout pipelineLayout, const int layerNdx)
1095 {
1096 const DeviceInterface &vk = m_context.getDeviceInterface();
1097 const VkDevice device = m_context.getDevice();
1098
1099 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1100 const VkImageView imageView = **m_allImageViews[layerNdx];
1101
1102 const VkDescriptorImageInfo descriptorImageInfo =
1103 makeDescriptorImageInfo(VK_NULL_HANDLE, imageView, VK_IMAGE_LAYOUT_GENERAL);
1104
1105 // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
1106 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
1107 m_constantsBuffer->get(), layerNdx * m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
1108
1109 DescriptorSetUpdateBuilder()
1110 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1111 &descriptorImageInfo)
1112 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1113 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
1114 .update(vk, device);
1115 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u,
1116 nullptr);
1117 }
1118
commandBeforeCompute(const VkCommandBuffer cmdBuffer)1119 void ImageStoreTestInstance::commandBeforeCompute(const VkCommandBuffer cmdBuffer)
1120 {
1121 const DeviceInterface &vk = m_context.getDeviceInterface();
1122 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
1123
1124 const VkImageSubresourceRange fullImageSubresourceRange =
1125 makeImageSubresourceRange(aspectMask, 0u, 1u, 0u, m_texture.numLayers());
1126 const VkImageMemoryBarrier setImageLayoutBarrier =
1127 makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1128 m_image->get(), fullImageSubresourceRange);
1129
1130 const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
1131 const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
1132 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, m_constantsBuffer->get(), 0ull, constantsBufferSize);
1133
1134 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1135 (VkDependencyFlags)0, 0, nullptr, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier);
1136 }
1137
commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)1138 void ImageStoreTestInstance::commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)
1139 {
1140 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
1141 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture, aspectMask);
1142 }
1143
commandAfterCompute(const VkCommandBuffer cmdBuffer)1144 void ImageStoreTestInstance::commandAfterCompute(const VkCommandBuffer cmdBuffer)
1145 {
1146 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
1147 commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture,
1148 aspectMask);
1149 }
1150
1151 //! Store test for buffers
1152 class BufferStoreTestInstance : public StoreTestInstance
1153 {
1154 public:
1155 BufferStoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
1156 const bool declareImageFormatInShader, const bool minalign, const bool storeConstantValue);
1157
1158 protected:
1159 VkDescriptorSetLayout prepareDescriptors(void);
1160 void commandAfterCompute(const VkCommandBuffer cmdBuffer);
1161
1162 void commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout,
1163 const int layerNdx);
1164
1165 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1166 Move<VkDescriptorPool> m_descriptorPool;
1167 Move<VkDescriptorSet> m_descriptorSet;
1168 Move<VkBufferView> m_bufferView;
1169 };
1170
BufferStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool declareImageFormatInShader,const bool minalign,const bool storeConstantValue)1171 BufferStoreTestInstance::BufferStoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
1172 const bool declareImageFormatInShader, const bool minalign,
1173 const bool storeConstantValue)
1174 : StoreTestInstance(context, texture, format, declareImageFormatInShader, false, minalign, storeConstantValue)
1175 {
1176 }
1177
prepareDescriptors(void)1178 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors(void)
1179 {
1180 const DeviceInterface &vk = m_context.getDeviceInterface();
1181 const VkDevice device = m_context.getDevice();
1182
1183 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1184 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1185 .build(vk, device);
1186
1187 m_descriptorPool = DescriptorPoolBuilder()
1188 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1189 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1190
1191 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1192 m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_dstViewOffset, m_imageSizeBytes);
1193
1194 return *m_descriptorSetLayout; // not passing the ownership
1195 }
1196
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)1197 void BufferStoreTestInstance::commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,
1198 const VkPipelineLayout pipelineLayout, const int layerNdx)
1199 {
1200 DE_ASSERT(layerNdx == 0);
1201 DE_UNREF(layerNdx);
1202
1203 const VkDevice device = m_context.getDevice();
1204 const DeviceInterface &vk = m_context.getDeviceInterface();
1205
1206 DescriptorSetUpdateBuilder()
1207 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1208 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
1209 .update(vk, device);
1210 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(),
1211 0u, nullptr);
1212 }
1213
commandAfterCompute(const VkCommandBuffer cmdBuffer)1214 void BufferStoreTestInstance::commandAfterCompute(const VkCommandBuffer cmdBuffer)
1215 {
1216 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(),
1217 m_imageSizeBytes + m_dstViewOffset);
1218 }
1219
1220 class LoadStoreTest : public TestCase
1221 {
1222 public:
1223 enum TestFlags
1224 {
1225 FLAG_SINGLE_LAYER_BIND = (1 << 0), //!< Run the shader multiple times, each time binding a different layer.
1226 FLAG_RESTRICT_IMAGES = (1 << 1), //!< If given, images in the shader will be qualified with "restrict".
1227 FLAG_DECLARE_FORMAT_IN_SHADER_READS = (1 << 2), //!< Declare the format of images being read in the shader code
1228 FLAG_DECLARE_FORMAT_IN_SHADER_WRITES = (1 << 3), //!< Declare the format of images being read in the shader code
1229 FLAG_MINALIGN = (1 << 4), //!< Use bufferview offset that matches the advertised minimum alignment
1230 FLAG_UNIFORM_TEXEL_BUFFER = (1 << 5), //!< Load from a uniform texel buffer rather than a storage texel buffer
1231 };
1232
1233 LoadStoreTest(tcu::TestContext &testCtx, const std::string &name, const Texture &texture, const VkFormat format,
1234 const VkFormat imageFormat, const VkImageTiling tiling,
1235 const uint32_t flags = (FLAG_DECLARE_FORMAT_IN_SHADER_READS | FLAG_DECLARE_FORMAT_IN_SHADER_WRITES),
1236 const bool imageLoadStoreLodAMD = false);
1237
1238 virtual void checkSupport(Context &context) const;
1239 void makePrograms(SourceCollections &programCollection, const DeviceScopeType deviceScopeType = DEVICESCOPE_NONE,
1240 const bool draw = false, const uint32_t verticesCount = 0u) const;
1241 virtual void initPrograms(SourceCollections &programCollection) const;
1242 TestInstance *createInstance(Context &context) const;
1243
1244 protected:
1245 const Texture m_texture;
1246 const VkFormat m_format; //!< Format as accessed in the shader
1247 const VkFormat m_imageFormat; //!< Storage format
1248 const VkImageTiling m_tiling; //!< Image Tiling
1249 const bool
1250 m_declareFormatInShaderReads; //!< Whether the shader will specify the format layout qualifier of images being read from.
1251 const bool
1252 m_declareFormatInShaderWrites; //!< Whether the shader will specify the format layout qualifier of images being written to.
1253 const bool m_singleLayerBind;
1254 const bool m_restrictImages;
1255 const bool m_minalign;
1256 bool m_bufferLoadUniform;
1257 const bool m_imageLoadStoreLodAMD;
1258 };
1259
LoadStoreTest(tcu::TestContext & testCtx,const std::string & name,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const VkImageTiling tiling,const uint32_t flags,const bool imageLoadStoreLodAMD)1260 LoadStoreTest::LoadStoreTest(tcu::TestContext &testCtx, const std::string &name, const Texture &texture,
1261 const VkFormat format, const VkFormat imageFormat, const VkImageTiling tiling,
1262 const uint32_t flags, const bool imageLoadStoreLodAMD)
1263 : TestCase(testCtx, name)
1264 , m_texture(texture)
1265 , m_format(format)
1266 , m_imageFormat(imageFormat)
1267 , m_tiling(tiling)
1268 , m_declareFormatInShaderReads((flags & FLAG_DECLARE_FORMAT_IN_SHADER_READS) != 0)
1269 , m_declareFormatInShaderWrites((flags & FLAG_DECLARE_FORMAT_IN_SHADER_WRITES) != 0)
1270 , m_singleLayerBind((flags & FLAG_SINGLE_LAYER_BIND) != 0)
1271 , m_restrictImages((flags & FLAG_RESTRICT_IMAGES) != 0)
1272 , m_minalign((flags & FLAG_MINALIGN) != 0)
1273 , m_bufferLoadUniform((flags & FLAG_UNIFORM_TEXEL_BUFFER) != 0)
1274 , m_imageLoadStoreLodAMD(imageLoadStoreLodAMD)
1275 {
1276 if (m_singleLayerBind)
1277 DE_ASSERT(m_texture.numLayers() > 1);
1278
1279 DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
1280 }
1281
checkSupport(Context & context) const1282 void LoadStoreTest::checkSupport(Context &context) const
1283 {
1284 #ifndef CTS_USES_VULKANSC
1285 if (m_format == VK_FORMAT_A8_UNORM_KHR || m_format == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
1286 context.requireDeviceFunctionality("VK_KHR_maintenance5");
1287
1288 const VkFormatProperties3 formatProperties(context.getFormatProperties(m_format));
1289 const VkFormatProperties3 imageFormatProperties(context.getFormatProperties(m_imageFormat));
1290
1291 const auto &tilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? formatProperties.optimalTilingFeatures :
1292 formatProperties.linearTilingFeatures;
1293 const auto &imageTilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ?
1294 imageFormatProperties.optimalTilingFeatures :
1295 imageFormatProperties.linearTilingFeatures;
1296
1297 if (m_imageLoadStoreLodAMD)
1298 context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1299
1300 if (!m_bufferLoadUniform && !m_declareFormatInShaderReads &&
1301 !(tilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT))
1302 TCU_THROW(NotSupportedError, "Format not supported for unformatted loads via storage images");
1303
1304 if (m_texture.type() == IMAGE_TYPE_BUFFER && !m_declareFormatInShaderReads &&
1305 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT))
1306 TCU_THROW(NotSupportedError, "Format not supported for unformatted loads via buffers");
1307
1308 if (!m_declareFormatInShaderWrites && !(tilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT))
1309 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage images");
1310
1311 if (m_texture.type() == IMAGE_TYPE_BUFFER && !m_declareFormatInShaderWrites &&
1312 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT))
1313 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via buffers");
1314
1315 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1316 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1317
1318 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(tilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1319 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1320
1321 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1322 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1323
1324 if (m_texture.type() == IMAGE_TYPE_BUFFER &&
1325 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1326 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1327
1328 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageTilingFeatures))
1329 TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1330
1331 if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1332 TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1333
1334 if (formatHasThreeComponents(m_format))
1335 {
1336 // When the source buffer is three-component, the destination buffer is single-component.
1337 VkFormat dstFormat = getSingleComponentFormat(m_format);
1338 const VkFormatProperties3 dstFormatProperties(context.getFormatProperties(dstFormat));
1339
1340 if (m_texture.type() == IMAGE_TYPE_BUFFER &&
1341 !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1342 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1343 }
1344 else if (m_texture.type() == IMAGE_TYPE_BUFFER &&
1345 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1346 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1347
1348 if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER &&
1349 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1350 TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1351 #else
1352 const vk::VkFormatProperties formatProperties(
1353 vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_format));
1354 const vk::VkFormatProperties imageFormatProperties(vk::getPhysicalDeviceFormatProperties(
1355 context.getInstanceInterface(), context.getPhysicalDevice(), m_imageFormat));
1356
1357 const auto tilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? formatProperties.optimalTilingFeatures :
1358 formatProperties.linearTilingFeatures;
1359 const auto imageTilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ?
1360 imageFormatProperties.optimalTilingFeatures :
1361 imageFormatProperties.linearTilingFeatures;
1362
1363 if (m_imageLoadStoreLodAMD)
1364 context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1365
1366 if (!m_bufferLoadUniform && !m_declareFormatInShaderReads)
1367 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT);
1368
1369 if (!m_declareFormatInShaderWrites)
1370 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
1371
1372 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1373 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1374
1375 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(tilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1376 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1377
1378 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1379 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1380
1381 if (m_texture.type() == IMAGE_TYPE_BUFFER &&
1382 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1383 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1384
1385 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageTilingFeatures))
1386 TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1387
1388 if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1389 TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1390
1391 if (formatHasThreeComponents(m_format))
1392 {
1393 // When the source buffer is three-component, the destination buffer is single-component.
1394 VkFormat dstFormat = getSingleComponentFormat(m_format);
1395 const vk::VkFormatProperties dstFormatProperties(vk::getPhysicalDeviceFormatProperties(
1396 context.getInstanceInterface(), context.getPhysicalDevice(), dstFormat));
1397
1398 if (m_texture.type() == IMAGE_TYPE_BUFFER &&
1399 !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1400 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1401 }
1402 else if (m_texture.type() == IMAGE_TYPE_BUFFER &&
1403 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1404 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1405
1406 if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER &&
1407 !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1408 TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1409 #endif // CTS_USES_VULKANSC
1410
1411 const auto &vki = context.getInstanceInterface();
1412 const auto physicalDevice = context.getPhysicalDevice();
1413
1414 VkImageFormatProperties vkImageFormatProperties;
1415 const auto result = vki.getPhysicalDeviceImageFormatProperties(
1416 physicalDevice, m_imageFormat, mapImageType(m_texture.type()), m_tiling,
1417 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0, &vkImageFormatProperties);
1418
1419 if (result != VK_SUCCESS)
1420 {
1421 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
1422 TCU_THROW(NotSupportedError, "Format unsupported for tiling");
1423 else
1424 TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned unexpected error");
1425 }
1426
1427 if (vkImageFormatProperties.maxArrayLayers < (uint32_t)m_texture.numLayers())
1428 {
1429 TCU_THROW(NotSupportedError, "This format and tiling combination does not support this number of aray layers");
1430 }
1431
1432 if (vkImageFormatProperties.maxMipLevels < (uint32_t)m_texture.numMipmapLevels())
1433 {
1434 TCU_THROW(NotSupportedError, "This format and tiling combination does not support this number of miplevels");
1435 }
1436 }
1437
makePrograms(SourceCollections & programCollection,const DeviceScopeType deviceScopeType,const bool draw,const uint32_t verticesCount) const1438 void LoadStoreTest::makePrograms(SourceCollections &programCollection, const DeviceScopeType deviceScopeType,
1439 const bool draw, const uint32_t verticesCount) const
1440 {
1441 const tcu::TextureFormat texFormat = mapVkFormat(m_format);
1442 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
1443 const ImageType usedImageType =
1444 (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
1445 const bool noFormats = (!m_declareFormatInShaderReads && !m_declareFormatInShaderWrites);
1446 const std::string formatQualifierStr = (noFormats ? "" : getShaderImageFormatQualifierStr(m_format));
1447 const std::string uniformTypeStr = getFormatPrefix(texFormat) + "textureBuffer";
1448 const std::string imageTypeStr = getShaderImageType(texFormat, usedImageType);
1449 const std::string maybeRestrictStr = (m_restrictImages ? "restrict " : "");
1450 const std::string xMax = de::toString(m_texture.size().x() - 1);
1451 const std::string xMaxSub = (deviceScopeType == DEVICESCOPE_LOAD) ? "" : (xMax + "-");
1452 const std::string maybeFmtQualStrReads = m_declareFormatInShaderReads ? ", " + formatQualifierStr : "";
1453 const std::string maybeFmtQualStrWrites = m_declareFormatInShaderWrites ? ", " + formatQualifierStr : "";
1454
1455 // For device scope tests, the output of first shader will become the input for the second shader
1456 const std::string inputBinding = (deviceScopeType == DEVICESCOPE_LOAD) ? "1" : "0";
1457 const std::string outputBinding = (deviceScopeType == DEVICESCOPE_LOAD) ? "0" : "1";
1458
1459 const std::string deviceScopeCommonHeader("#pragma use_vulkan_memory_model\n"
1460 "#extension GL_KHR_memory_scope_semantics : enable\n");
1461 if (!draw)
1462 {
1463 std::string shaderName = "comp";
1464
1465 std::ostringstream src;
1466 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1467 << "\n";
1468
1469 if (deviceScopeType != DEVICESCOPE_NONE)
1470 {
1471 src << deviceScopeCommonHeader;
1472 }
1473
1474 if (!m_declareFormatInShaderReads || !m_declareFormatInShaderWrites)
1475 {
1476 src << "#extension GL_EXT_shader_image_load_formatted : require\n";
1477 }
1478
1479 if (m_imageLoadStoreLodAMD)
1480 {
1481 src << "#extension GL_AMD_shader_image_load_store_lod : require\n";
1482 }
1483
1484 src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
1485
1486 if (m_bufferLoadUniform)
1487 src << "layout (binding = " << inputBinding << ") uniform " << uniformTypeStr << " u_image0;\n";
1488 else
1489 src << "layout (binding = " << inputBinding << maybeFmtQualStrReads << ") " << maybeRestrictStr
1490 << "readonly uniform " << imageTypeStr << " u_image0;\n";
1491
1492 // For three-component formats, the dst buffer is single-component and the shader expands the store into 3 component-wise stores.
1493 // We always use the format qualifier for the dst buffer, except when splitting it up.
1494 if (formatHasThreeComponents(m_format))
1495 src << "layout (binding = " << outputBinding << ") " << maybeRestrictStr << "writeonly uniform "
1496 << imageTypeStr << " u_image1;\n";
1497 else
1498 src << "layout (binding = " << outputBinding << maybeFmtQualStrWrites << ") " << maybeRestrictStr
1499 << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1500
1501 src << "\n"
1502 << "void main (void)\n"
1503 << "{\n";
1504
1505 if (deviceScopeType == DEVICESCOPE_LOAD)
1506 {
1507 src << " memoryBarrier(gl_ScopeDevice, gl_StorageSemanticsImage, gl_SemanticsAcquireRelease | "
1508 "gl_SemanticsMakeVisible);\n";
1509 }
1510
1511 switch (dimension)
1512 {
1513 default:
1514 DE_ASSERT(0); // fallthrough
1515 case 1:
1516 if (m_bufferLoadUniform)
1517 {
1518 // Expand the store into 3 component-wise stores.
1519 std::string type = getFormatPrefix(texFormat) + "vec4";
1520 src << " int pos = int(gl_GlobalInvocationID.x);\n"
1521 " "
1522 << type << " t = texelFetch(u_image0, " + xMax + "-pos);\n";
1523 if (formatHasThreeComponents(m_format))
1524 {
1525 src << " imageStore(u_image1, 3*pos+0, " << type << "(t.x));\n";
1526 src << " imageStore(u_image1, 3*pos+1, " << type << "(t.y));\n";
1527 src << " imageStore(u_image1, 3*pos+2, " << type << "(t.z));\n";
1528 }
1529 else
1530 src << " imageStore(u_image1, pos, t);\n";
1531 }
1532 else if (m_imageLoadStoreLodAMD)
1533 {
1534 src << " int pos = int(gl_GlobalInvocationID.x);\n";
1535
1536 for (int32_t levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1537 {
1538 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1539 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) +
1540 ", imageLoadLodAMD(u_image0, " + xMaxSize + "-pos, " + de::toString(levelNdx) + "));\n";
1541 }
1542 }
1543 else
1544 {
1545 src << " int pos = int(gl_GlobalInvocationID.x);\n"
1546 " imageStore(u_image1, pos, imageLoad(u_image0, " +
1547 xMaxSub + "pos));\n";
1548 }
1549 break;
1550 case 2:
1551 if (m_imageLoadStoreLodAMD)
1552 {
1553 src << " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
1554
1555 for (int32_t levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1556 {
1557 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1558 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) +
1559 ", imageLoadLodAMD(u_image0, ivec2(" + xMaxSize + "-pos.x, pos.y), " +
1560 de::toString(levelNdx) + "));\n";
1561 }
1562 }
1563 else
1564 {
1565 src << " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
1566 " imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" +
1567 xMaxSub + "pos.x, pos.y)));\n";
1568 }
1569 break;
1570 case 3:
1571 if (m_imageLoadStoreLodAMD)
1572 {
1573 src << " ivec3 pos = ivec3(gl_GlobalInvocationID);\n";
1574
1575 for (int32_t levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1576 {
1577 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1578 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) +
1579 ", imageLoadLodAMD(u_image0, ivec3(" + xMaxSize + "-pos.x, pos.y, pos.z), " +
1580 de::toString(levelNdx) + "));\n";
1581 }
1582 }
1583 else
1584 {
1585 src << " ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
1586 " imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" +
1587 xMaxSub + "pos.x, pos.y, pos.z)));\n";
1588 }
1589 break;
1590 }
1591
1592 if (deviceScopeType == DEVICESCOPE_STORE)
1593 {
1594 src << " memoryBarrier(gl_ScopeDevice, gl_StorageSemanticsImage, gl_SemanticsAcquireRelease | "
1595 "gl_SemanticsMakeAvailable);\n";
1596 }
1597
1598 src << "}\n";
1599
1600 if (deviceScopeType == DEVICESCOPE_STORE)
1601 shaderName += "_store";
1602 else if (deviceScopeType == DEVICESCOPE_LOAD)
1603 shaderName += "_load";
1604
1605 programCollection.glslSources.add(shaderName) << glu::ComputeSource(src.str());
1606 }
1607 else
1608 {
1609 std::ostringstream srcVert;
1610
1611 srcVert << glu::getGLSLVersionDeclaration(glu::GLSLVersion::GLSL_VERSION_450) << "\n";
1612
1613 srcVert << "vec4 positions[" << verticesCount << "] = vec4[](\n"
1614 << " vec4(-1.0f, -1.0f, 1.0f, 1.0f),\n"
1615 << " vec4( 1.0f, -1.0f, 1.0f, 1.0f),\n"
1616 << " vec4(-1.0f, 1.0f, 1.0f, 1.0f),\n"
1617 << " vec4(-1.0f, 1.0f, 1.0f, 1.0f),\n"
1618 << " vec4( 1.0f, -1.0f, 1.0f, 1.0f),\n"
1619 << " vec4( 1.0f, 1.0f, 1.0f, 1.0f)\n"
1620 << ");\n"
1621 << "\n"
1622 << "void main() {\n"
1623 << " gl_Position = positions[gl_VertexIndex];\n"
1624 << "}\n";
1625
1626 programCollection.glslSources.add("vert") << glu::VertexSource(srcVert.str());
1627
1628 std::ostringstream srcFrag;
1629
1630 srcFrag << glu::getGLSLVersionDeclaration(glu::GLSLVersion::GLSL_VERSION_450) << "\n";
1631 srcFrag << deviceScopeCommonHeader;
1632
1633 srcFrag << "layout (binding = " << inputBinding << maybeFmtQualStrReads << ") " << maybeRestrictStr
1634 << "readonly uniform " << imageTypeStr << " u_image0;\n";
1635
1636 const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
1637 const std::string colorType = signednessPrefix + "vec4";
1638
1639 srcFrag << "layout (location=0) out " << colorType << " outcolor;\n";
1640 srcFrag << "\n"
1641 << "void main (void)\n"
1642 << "{\n";
1643
1644 if (deviceScopeType == DEVICESCOPE_LOAD)
1645 {
1646 srcFrag << " memoryBarrier(gl_ScopeDevice, gl_StorageSemanticsImage, gl_SemanticsAcquireRelease | "
1647 "gl_SemanticsMakeVisible);\n";
1648 }
1649
1650 switch (dimension)
1651 {
1652 default:
1653 DE_ASSERT(0); // fallthrough
1654 case 1:
1655 {
1656 srcFrag << " int pos = int(gl_FragCoord.x);\n"
1657 " outcolor = imageLoad(u_image0, pos);\n";
1658 }
1659 break;
1660 case 2:
1661 {
1662 srcFrag << " ivec2 pos = ivec2(gl_FragCoord.xy);\n"
1663 " outcolor = imageLoad(u_image0, ivec2(pos.x, pos.y));\n";
1664 }
1665 break;
1666 case 3:
1667 {
1668 srcFrag << " ivec3 pos = ivec3(gl_FragCoord.xyz);\n"
1669 " outcolor = imageLoad(u_image0, ivec3(pos.x, pos.y, pos.z));\n";
1670 }
1671 break;
1672 }
1673 srcFrag << "}\n";
1674
1675 programCollection.glslSources.add("frag") << glu::FragmentSource(srcFrag.str());
1676 }
1677 }
1678
initPrograms(SourceCollections & programCollection) const1679 void LoadStoreTest::initPrograms(SourceCollections &programCollection) const
1680 {
1681 makePrograms(programCollection);
1682 }
1683
1684 //! Load/store test base implementation
1685 class LoadStoreTestInstance : public BaseTestInstance
1686 {
1687 public:
1688 LoadStoreTestInstance(Context &context, const Texture &texture, const VkFormat format, const VkFormat imageFormat,
1689 const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign,
1690 const bool bufferLoadUniform);
1691
1692 protected:
1693 virtual BufferWithMemory *getResultBuffer(void) const = 0; //!< Get the buffer that contains the result image
1694
1695 tcu::TestStatus verifyResult(void);
1696
1697 // Add empty implementations for functions that might be not needed
commandBeforeCompute(const VkCommandBuffer)1698 void commandBeforeCompute(const VkCommandBuffer)
1699 {
1700 }
commandBetweenShaderInvocations(const VkCommandBuffer)1701 void commandBetweenShaderInvocations(const VkCommandBuffer)
1702 {
1703 }
commandAfterCompute(const VkCommandBuffer)1704 void commandAfterCompute(const VkCommandBuffer)
1705 {
1706 }
1707
1708 de::MovePtr<BufferWithMemory> m_imageBuffer; //!< Source data and helper buffer
1709 const VkDeviceSize m_imageSizeBytes;
1710 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
1711 tcu::TextureLevel m_referenceImage; //!< Used as input data and later to verify result image
1712
1713 bool m_bufferLoadUniform;
1714 VkDescriptorType m_bufferLoadDescriptorType;
1715 VkBufferUsageFlagBits m_bufferLoadUsageBit;
1716 };
1717
LoadStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool bufferLoadUniform)1718 LoadStoreTestInstance::LoadStoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
1719 const VkFormat imageFormat, const bool declareImageFormatInShader,
1720 const bool singleLayerBind, const bool minalign,
1721 const bool bufferLoadUniform)
1722 : BaseTestInstance(context, texture, format, declareImageFormatInShader, singleLayerBind, minalign,
1723 bufferLoadUniform)
1724 , m_imageSizeBytes(getImageSizeBytes(texture.size(), format))
1725 , m_imageFormat(imageFormat)
1726 , m_referenceImage(generateReferenceImage(texture.size(), imageFormat, format))
1727 , m_bufferLoadUniform(bufferLoadUniform)
1728 {
1729 const DeviceInterface &vk = m_context.getDeviceInterface();
1730 const VkDevice device = m_context.getDevice();
1731 Allocator &allocator = m_context.getDefaultAllocator();
1732
1733 m_bufferLoadDescriptorType =
1734 m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1735 m_bufferLoadUsageBit =
1736 m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1737
1738 // A helper buffer with enough space to hold the whole image.
1739
1740 m_imageBuffer = de::MovePtr<BufferWithMemory>(
1741 new BufferWithMemory(vk, device, allocator,
1742 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset,
1743 m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
1744 VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1745 MemoryRequirement::HostVisible));
1746
1747 // Copy reference data to buffer for subsequent upload to image.
1748
1749 const Allocation &alloc = m_imageBuffer->getAllocation();
1750 deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset, m_referenceImage.getAccess().getDataPtr(),
1751 static_cast<size_t>(m_imageSizeBytes));
1752 flushAlloc(vk, device, alloc);
1753 }
1754
verifyResult(void)1755 tcu::TestStatus LoadStoreTestInstance::verifyResult(void)
1756 {
1757 const DeviceInterface &vk = m_context.getDeviceInterface();
1758 const VkDevice device = m_context.getDevice();
1759
1760 // Apply the same transformation as done in the shader
1761 const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
1762 flipHorizontally(reference);
1763
1764 const Allocation &alloc = getResultBuffer()->getAllocation();
1765 invalidateAlloc(vk, device, alloc);
1766 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(),
1767 (const char *)alloc.getHostPtr() + m_dstViewOffset);
1768
1769 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
1770 return tcu::TestStatus::pass("Passed");
1771 else
1772 return tcu::TestStatus::fail("Image comparison failed");
1773 }
1774
1775 //! Load/store test for images
1776 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
1777 {
1778 public:
1779 ImageLoadStoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
1780 const VkFormat imageFormat, const VkImageTiling tiling,
1781 const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign,
1782 const bool bufferLoadUniform);
1783
1784 protected:
1785 VkDescriptorSetLayout commonPrepareDescriptors(const VkShaderStageFlags stageFlags);
1786 VkDescriptorSetLayout prepareDescriptors(void);
1787 void commandBeforeCompute(const VkCommandBuffer cmdBuffer);
1788 void commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer);
1789 void commandAfterCompute(const VkCommandBuffer cmdBuffer);
1790
1791 void commonBindDescriptors(const VkCommandBuffer cmdBuffer, const VkPipelineBindPoint pipelineBinding,
1792 const VkPipelineLayout pipelineLayout, const int layerNdx);
1793 void commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout,
1794 const int layerNdx);
1795
getResultBuffer(void) const1796 BufferWithMemory *getResultBuffer(void) const
1797 {
1798 return m_imageBuffer.get();
1799 }
1800
1801 de::MovePtr<Image> m_imageSrc;
1802 de::MovePtr<Image> m_imageDst;
1803 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1804 Move<VkDescriptorPool> m_descriptorPool;
1805 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1806 std::vector<SharedVkImageView> m_allSrcImageViews;
1807 std::vector<SharedVkImageView> m_allDstImageViews;
1808 };
1809
ImageLoadStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const VkImageTiling tiling,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool bufferLoadUniform)1810 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
1811 const VkFormat imageFormat, const VkImageTiling tiling,
1812 const bool declareImageFormatInShader,
1813 const bool singleLayerBind, const bool minalign,
1814 const bool bufferLoadUniform)
1815 : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind,
1816 minalign, bufferLoadUniform)
1817 , m_allDescriptorSets(texture.numLayers())
1818 , m_allSrcImageViews(texture.numLayers())
1819 , m_allDstImageViews(texture.numLayers())
1820 {
1821 const DeviceInterface &vk = m_context.getDeviceInterface();
1822 const VkDevice device = m_context.getDevice();
1823 Allocator &allocator = m_context.getDefaultAllocator();
1824 const VkImageCreateFlags imageFlags =
1825 (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1826
1827 m_imageSrc =
1828 de::MovePtr<Image>(new Image(vk, device, allocator,
1829 makeImageCreateInfo(m_texture, m_imageFormat,
1830 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1831 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1832 imageFlags, tiling),
1833 MemoryRequirement::Any));
1834
1835 m_imageDst =
1836 de::MovePtr<Image>(new Image(vk, device, allocator,
1837 makeImageCreateInfo(m_texture, m_imageFormat,
1838 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1839 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1840 imageFlags, tiling),
1841 MemoryRequirement::Any));
1842 }
1843
commonPrepareDescriptors(const VkShaderStageFlags stageFlags)1844 VkDescriptorSetLayout ImageLoadStoreTestInstance::commonPrepareDescriptors(const VkShaderStageFlags stageFlags)
1845 {
1846 const VkDevice device = m_context.getDevice();
1847 const DeviceInterface &vk = m_context.getDeviceInterface();
1848
1849 const int numLayers = m_texture.numLayers();
1850 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1851 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stageFlags)
1852 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stageFlags)
1853 .build(vk, device);
1854
1855 m_descriptorPool = DescriptorPoolBuilder()
1856 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1857 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1858 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1859
1860 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
1861
1862 if (m_singleLayerBind)
1863 {
1864 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1865 {
1866 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1867 const VkImageSubresourceRange subresourceRange =
1868 makeImageSubresourceRange(aspectMask, 0u, 1u, layerNdx, 1u);
1869
1870 m_allDescriptorSets[layerNdx] =
1871 makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1872 m_allSrcImageViews[layerNdx] =
1873 makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1874 m_allDstImageViews[layerNdx] =
1875 makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1876 }
1877 }
1878 else // bind all layers at once
1879 {
1880 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1881 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(aspectMask, 0u, 1u, 0u, numLayers);
1882
1883 m_allDescriptorSets[0] =
1884 makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1885 m_allSrcImageViews[0] =
1886 makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1887 m_allDstImageViews[0] =
1888 makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1889 }
1890
1891 return *m_descriptorSetLayout; // not passing the ownership
1892 }
1893
prepareDescriptors(void)1894 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors(void)
1895 {
1896 return commonPrepareDescriptors(VK_SHADER_STAGE_COMPUTE_BIT);
1897 }
1898
commonBindDescriptors(const VkCommandBuffer cmdBuffer,const VkPipelineBindPoint pipelineBinding,const VkPipelineLayout pipelineLayout,const int layerNdx)1899 void ImageLoadStoreTestInstance::commonBindDescriptors(const VkCommandBuffer cmdBuffer,
1900 const VkPipelineBindPoint pipelineBinding,
1901 const VkPipelineLayout pipelineLayout, const int layerNdx)
1902 {
1903 const VkDevice device = m_context.getDevice();
1904 const DeviceInterface &vk = m_context.getDeviceInterface();
1905
1906 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1907 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
1908 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
1909
1910 const VkDescriptorImageInfo descriptorSrcImageInfo =
1911 makeDescriptorImageInfo(VK_NULL_HANDLE, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1912 const VkDescriptorImageInfo descriptorDstImageInfo =
1913 makeDescriptorImageInfo(VK_NULL_HANDLE, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1914
1915 DescriptorSetUpdateBuilder()
1916 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1917 &descriptorSrcImageInfo)
1918 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1919 &descriptorDstImageInfo)
1920 .update(vk, device);
1921 vk.cmdBindDescriptorSets(cmdBuffer, pipelineBinding, pipelineLayout, 0u, 1u, &descriptorSet, 0u, nullptr);
1922 }
1923
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)1924 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,
1925 const VkPipelineLayout pipelineLayout,
1926 const int layerNdx)
1927 {
1928 commonBindDescriptors(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, layerNdx);
1929 }
1930
commandBeforeCompute(const VkCommandBuffer cmdBuffer)1931 void ImageLoadStoreTestInstance::commandBeforeCompute(const VkCommandBuffer cmdBuffer)
1932 {
1933 const DeviceInterface &vk = m_context.getDeviceInterface();
1934 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
1935
1936 const VkImageSubresourceRange fullImageSubresourceRange =
1937 makeImageSubresourceRange(aspectMask, 0u, 1u, 0u, m_texture.numLayers());
1938 {
1939 const VkImageMemoryBarrier preCopyImageBarriers[] = {
1940 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1941 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_imageSrc->get(), fullImageSubresourceRange),
1942 makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1943 m_imageDst->get(), fullImageSubresourceRange)};
1944
1945 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy =
1946 makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, m_imageBuffer->get(), 0ull,
1947 m_imageSizeBytes + m_srcViewOffset);
1948
1949 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
1950 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1951 (VkDependencyFlags)0, 0, nullptr, 1, &barrierFlushHostWriteBeforeCopy,
1952 DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1953 }
1954 {
1955 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1956 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1957 VK_IMAGE_LAYOUT_GENERAL, m_imageSrc->get(), fullImageSubresourceRange);
1958
1959 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture, aspectMask);
1960
1961 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(),
1962 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
1963 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1964 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &barrierAfterCopy);
1965 }
1966 }
1967
commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)1968 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)
1969 {
1970 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
1971 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture, aspectMask);
1972 }
1973
commandAfterCompute(const VkCommandBuffer cmdBuffer)1974 void ImageLoadStoreTestInstance::commandAfterCompute(const VkCommandBuffer cmdBuffer)
1975 {
1976 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
1977 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture,
1978 aspectMask);
1979 }
1980
1981 //! Load/store Lod AMD test for images
1982 class ImageLoadStoreLodAMDTestInstance : public BaseTestInstance
1983 {
1984 public:
1985 ImageLoadStoreLodAMDTestInstance(Context &context, const Texture &texture, const VkFormat format,
1986 const VkFormat imageFormat, const bool declareImageFormatInShader,
1987 const bool singleLayerBind, const bool minalign, const bool bufferLoadUniform);
1988
1989 protected:
1990 VkDescriptorSetLayout prepareDescriptors(void);
1991 void commandBeforeCompute(const VkCommandBuffer cmdBuffer);
1992 void commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer);
1993 void commandAfterCompute(const VkCommandBuffer cmdBuffer);
1994
1995 void commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout,
1996 const int layerNdx);
1997
getResultBuffer(void) const1998 BufferWithMemory *getResultBuffer(void) const
1999 {
2000 return m_imageBuffer.get();
2001 }
2002 tcu::TestStatus verifyResult(void);
2003
2004 de::MovePtr<BufferWithMemory> m_imageBuffer; //!< Source data and helper buffer
2005 const VkDeviceSize m_imageSizeBytes;
2006 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
2007 std::vector<tcu::TextureLevel> m_referenceImages; //!< Used as input data and later to verify result image
2008
2009 bool m_bufferLoadUniform;
2010 VkDescriptorType m_bufferLoadDescriptorType;
2011 VkBufferUsageFlagBits m_bufferLoadUsageBit;
2012
2013 de::MovePtr<Image> m_imageSrc;
2014 de::MovePtr<Image> m_imageDst;
2015 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2016 Move<VkDescriptorPool> m_descriptorPool;
2017 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
2018 std::vector<SharedVkImageView> m_allSrcImageViews;
2019 std::vector<SharedVkImageView> m_allDstImageViews;
2020 };
2021
ImageLoadStoreLodAMDTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool bufferLoadUniform)2022 ImageLoadStoreLodAMDTestInstance::ImageLoadStoreLodAMDTestInstance(Context &context, const Texture &texture,
2023 const VkFormat format, const VkFormat imageFormat,
2024 const bool declareImageFormatInShader,
2025 const bool singleLayerBind, const bool minalign,
2026 const bool bufferLoadUniform)
2027 : BaseTestInstance(context, texture, format, declareImageFormatInShader, singleLayerBind, minalign,
2028 bufferLoadUniform)
2029 , m_imageSizeBytes(getMipmapImageTotalSizeBytes(texture, format))
2030 , m_imageFormat(imageFormat)
2031 , m_bufferLoadUniform(bufferLoadUniform)
2032 , m_allDescriptorSets(texture.numLayers())
2033 , m_allSrcImageViews(texture.numLayers())
2034 , m_allDstImageViews(texture.numLayers())
2035 {
2036 const DeviceInterface &vk = m_context.getDeviceInterface();
2037 const VkDevice device = m_context.getDevice();
2038 Allocator &allocator = m_context.getDefaultAllocator();
2039 const VkImageCreateFlags imageFlags =
2040 (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
2041
2042 const VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(
2043 m_texture.numSamples()); // integer and bit mask are aligned, so we can cast like this
2044
2045 for (int32_t levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
2046 {
2047 tcu::TextureLevel referenceImage = generateReferenceImage(texture.size(levelNdx), imageFormat, format);
2048 m_referenceImages.push_back(referenceImage);
2049 }
2050
2051 m_bufferLoadDescriptorType =
2052 m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
2053 m_bufferLoadUsageBit =
2054 m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
2055
2056 // A helper buffer with enough space to hold the whole image.
2057 m_imageBuffer = de::MovePtr<BufferWithMemory>(
2058 new BufferWithMemory(vk, device, allocator,
2059 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset,
2060 m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
2061 VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
2062 MemoryRequirement::HostVisible));
2063
2064 // Copy reference data to buffer for subsequent upload to image.
2065 {
2066 const Allocation &alloc = m_imageBuffer->getAllocation();
2067 VkDeviceSize bufferOffset = 0u;
2068 for (int32_t levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
2069 {
2070 deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset + bufferOffset,
2071 m_referenceImages[levelNdx].getAccess().getDataPtr(),
2072 static_cast<size_t>(getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx)));
2073 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
2074 }
2075 flushAlloc(vk, device, alloc);
2076 }
2077
2078 {
2079 const VkImageCreateInfo imageParamsSrc = {
2080 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2081 nullptr, // const void* pNext;
2082 (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) |
2083 imageFlags, // VkImageCreateFlags flags;
2084 mapImageType(m_texture.type()), // VkImageType imageType;
2085 m_imageFormat, // VkFormat format;
2086 makeExtent3D(m_texture.layerSize()), // VkExtent3D extent;
2087 (uint32_t)m_texture.numMipmapLevels(), // uint32_t mipLevels;
2088 (uint32_t)m_texture.numLayers(), // uint32_t arrayLayers;
2089 samples, // VkSampleCountFlagBits samples;
2090 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2091 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
2092 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2093 0u, // uint32_t queueFamilyIndexCount;
2094 nullptr, // const uint32_t* pQueueFamilyIndices;
2095 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2096 };
2097
2098 m_imageSrc = de::MovePtr<Image>(new Image(vk, device, allocator, imageParamsSrc, MemoryRequirement::Any));
2099 }
2100
2101 {
2102 const VkImageCreateInfo imageParamsDst = {
2103 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2104 nullptr, // const void* pNext;
2105 (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) |
2106 imageFlags, // VkImageCreateFlags flags;
2107 mapImageType(m_texture.type()), // VkImageType imageType;
2108 m_imageFormat, // VkFormat format;
2109 makeExtent3D(m_texture.layerSize()), // VkExtent3D extent;
2110 (uint32_t)m_texture.numMipmapLevels(), // uint32_t mipLevels;
2111 (uint32_t)m_texture.numLayers(), // uint32_t arrayLayers;
2112 samples, // VkSampleCountFlagBits samples;
2113 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2114 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
2115 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2116 0u, // uint32_t queueFamilyIndexCount;
2117 nullptr, // const uint32_t* pQueueFamilyIndices;
2118 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2119 };
2120
2121 m_imageDst = de::MovePtr<Image>(new Image(vk, device, allocator, imageParamsDst, MemoryRequirement::Any));
2122 }
2123 }
2124
verifyResult(void)2125 tcu::TestStatus ImageLoadStoreLodAMDTestInstance::verifyResult(void)
2126 {
2127 const DeviceInterface &vk = m_context.getDeviceInterface();
2128 const VkDevice device = m_context.getDevice();
2129
2130 const Allocation &alloc = getResultBuffer()->getAllocation();
2131 invalidateAlloc(vk, device, alloc);
2132
2133 VkDeviceSize bufferOffset = 0;
2134 for (int32_t levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
2135 {
2136 // Apply the same transformation as done in the shader
2137 const tcu::PixelBufferAccess reference = m_referenceImages[levelNdx].getAccess();
2138 flipHorizontally(reference);
2139
2140 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(levelNdx),
2141 (const char *)alloc.getHostPtr() + m_dstViewOffset + bufferOffset);
2142
2143 if (!comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result,
2144 levelNdx))
2145 {
2146 std::ostringstream errorMessage;
2147 errorMessage << "Image Level " << levelNdx << " comparison failed";
2148 return tcu::TestStatus::fail(errorMessage.str());
2149 }
2150 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
2151 }
2152
2153 return tcu::TestStatus::pass("Passed");
2154 }
2155
prepareDescriptors(void)2156 VkDescriptorSetLayout ImageLoadStoreLodAMDTestInstance::prepareDescriptors(void)
2157 {
2158 const VkDevice device = m_context.getDevice();
2159 const DeviceInterface &vk = m_context.getDeviceInterface();
2160
2161 const int numLayers = m_texture.numLayers();
2162 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2163 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2164 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2165 .build(vk, device);
2166
2167 m_descriptorPool = DescriptorPoolBuilder()
2168 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
2169 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
2170 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
2171
2172 if (m_singleLayerBind)
2173 {
2174 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
2175 {
2176 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
2177 const VkImageSubresourceRange subresourceRange =
2178 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), layerNdx, 1u);
2179
2180 m_allDescriptorSets[layerNdx] =
2181 makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
2182 m_allSrcImageViews[layerNdx] =
2183 makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
2184 m_allDstImageViews[layerNdx] =
2185 makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
2186 }
2187 }
2188 else // bind all layers at once
2189 {
2190 const VkImageViewType viewType = mapImageViewType(m_texture.type());
2191 const VkImageSubresourceRange subresourceRange =
2192 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, numLayers);
2193
2194 m_allDescriptorSets[0] =
2195 makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
2196 m_allSrcImageViews[0] =
2197 makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
2198 m_allDstImageViews[0] =
2199 makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
2200 }
2201
2202 return *m_descriptorSetLayout; // not passing the ownership
2203 }
2204
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)2205 void ImageLoadStoreLodAMDTestInstance::commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,
2206 const VkPipelineLayout pipelineLayout,
2207 const int layerNdx)
2208 {
2209 const VkDevice device = m_context.getDevice();
2210 const DeviceInterface &vk = m_context.getDeviceInterface();
2211
2212 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
2213 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
2214 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
2215
2216 const VkDescriptorImageInfo descriptorSrcImageInfo =
2217 makeDescriptorImageInfo(VK_NULL_HANDLE, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
2218 const VkDescriptorImageInfo descriptorDstImageInfo =
2219 makeDescriptorImageInfo(VK_NULL_HANDLE, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
2220
2221 DescriptorSetUpdateBuilder()
2222 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
2223 &descriptorSrcImageInfo)
2224 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
2225 &descriptorDstImageInfo)
2226 .update(vk, device);
2227 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u,
2228 nullptr);
2229 }
2230
commandBeforeCompute(const VkCommandBuffer cmdBuffer)2231 void ImageLoadStoreLodAMDTestInstance::commandBeforeCompute(const VkCommandBuffer cmdBuffer)
2232 {
2233 const DeviceInterface &vk = m_context.getDeviceInterface();
2234 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(
2235 VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, m_texture.numLayers());
2236 {
2237 const VkImageMemoryBarrier preCopyImageBarriers[] = {
2238 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2239 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_imageSrc->get(), fullImageSubresourceRange),
2240 makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
2241 m_imageDst->get(), fullImageSubresourceRange)};
2242
2243 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy =
2244 makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, m_imageBuffer->get(), 0ull,
2245 m_imageSizeBytes + m_srcViewOffset);
2246
2247 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
2248 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
2249 (VkDependencyFlags)0, 0, nullptr, 1, &barrierFlushHostWriteBeforeCopy,
2250 DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
2251 }
2252 {
2253 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
2254 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2255 VK_IMAGE_LAYOUT_GENERAL, m_imageSrc->get(), fullImageSubresourceRange);
2256
2257 std::vector<VkBufferImageCopy> copyRegions;
2258 VkDeviceSize bufferOffset = 0u;
2259 for (int32_t levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
2260 {
2261 const VkBufferImageCopy copyParams = {
2262 bufferOffset, // VkDeviceSize bufferOffset;
2263 0u, // uint32_t bufferRowLength;
2264 0u, // uint32_t bufferImageHeight;
2265 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u,
2266 m_texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
2267 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
2268 makeExtent3D(m_texture.layerSize(levelNdx)), // VkExtent3D imageExtent;
2269 };
2270 copyRegions.push_back(copyParams);
2271 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
2272 }
2273
2274 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(),
2275 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (uint32_t)copyRegions.size(), copyRegions.data());
2276 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2277 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &barrierAfterCopy);
2278 }
2279 }
2280
commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)2281 void ImageLoadStoreLodAMDTestInstance::commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)
2282 {
2283 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
2284 }
2285
commandAfterCompute(const VkCommandBuffer cmdBuffer)2286 void ImageLoadStoreLodAMDTestInstance::commandAfterCompute(const VkCommandBuffer cmdBuffer)
2287 {
2288 commandCopyMipmapImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageFormat, m_imageBuffer->get(),
2289 m_imageSizeBytes, m_texture);
2290 }
2291
2292 //! Load/store test for buffers
2293 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
2294 {
2295 public:
2296 BufferLoadStoreTestInstance(Context &context, const Texture &texture, const VkFormat format,
2297 const VkFormat imageFormat, const bool declareImageFormatInShader, const bool minalign,
2298 const bool bufferLoadUniform);
2299
2300 protected:
2301 VkDescriptorSetLayout prepareDescriptors(void);
2302 void commandAfterCompute(const VkCommandBuffer cmdBuffer);
2303
2304 void commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout,
2305 const int layerNdx);
2306
getResultBuffer(void) const2307 BufferWithMemory *getResultBuffer(void) const
2308 {
2309 return m_imageBufferDst.get();
2310 }
2311
2312 de::MovePtr<BufferWithMemory> m_imageBufferDst;
2313 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2314 Move<VkDescriptorPool> m_descriptorPool;
2315 Move<VkDescriptorSet> m_descriptorSet;
2316 Move<VkBufferView> m_bufferViewSrc;
2317 Move<VkBufferView> m_bufferViewDst;
2318 };
2319
BufferLoadStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const bool declareImageFormatInShader,const bool minalign,const bool bufferLoadUniform)2320 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance(Context &context, const Texture &texture,
2321 const VkFormat format, const VkFormat imageFormat,
2322 const bool declareImageFormatInShader, const bool minalign,
2323 const bool bufferLoadUniform)
2324 : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false, minalign,
2325 bufferLoadUniform)
2326 {
2327 const DeviceInterface &vk = m_context.getDeviceInterface();
2328 const VkDevice device = m_context.getDevice();
2329 Allocator &allocator = m_context.getDefaultAllocator();
2330
2331 // Create a destination buffer.
2332
2333 m_imageBufferDst = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
2334 vk, device, allocator,
2335 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
2336 MemoryRequirement::HostVisible));
2337 }
2338
prepareDescriptors(void)2339 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors(void)
2340 {
2341 const DeviceInterface &vk = m_context.getDeviceInterface();
2342 const VkDevice device = m_context.getDevice();
2343
2344 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2345 .addSingleBinding(m_bufferLoadDescriptorType, VK_SHADER_STAGE_COMPUTE_BIT)
2346 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2347 .build(vk, device);
2348
2349 m_descriptorPool = DescriptorPoolBuilder()
2350 .addType(m_bufferLoadDescriptorType)
2351 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
2352 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2353
2354 VkFormat dstFormat = formatHasThreeComponents(m_format) ? getSingleComponentFormat(m_format) : m_format;
2355
2356 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2357 m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_srcViewOffset, m_imageSizeBytes);
2358 m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), dstFormat, m_dstViewOffset, m_imageSizeBytes);
2359
2360 return *m_descriptorSetLayout; // not passing the ownership
2361 }
2362
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)2363 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,
2364 const VkPipelineLayout pipelineLayout,
2365 const int layerNdx)
2366 {
2367 DE_ASSERT(layerNdx == 0);
2368 DE_UNREF(layerNdx);
2369
2370 const VkDevice device = m_context.getDevice();
2371 const DeviceInterface &vk = m_context.getDeviceInterface();
2372
2373 DescriptorSetUpdateBuilder()
2374 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), m_bufferLoadDescriptorType,
2375 &m_bufferViewSrc.get())
2376 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
2377 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
2378 .update(vk, device);
2379 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(),
2380 0u, nullptr);
2381 }
2382
commandAfterCompute(const VkCommandBuffer cmdBuffer)2383 void BufferLoadStoreTestInstance::commandAfterCompute(const VkCommandBuffer cmdBuffer)
2384 {
2385 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(),
2386 m_imageSizeBytes + m_dstViewOffset);
2387 }
2388
createInstance(Context & context) const2389 TestInstance *StoreTest::createInstance(Context &context) const
2390 {
2391 if (m_texture.type() == IMAGE_TYPE_BUFFER)
2392 return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_minalign,
2393 m_storeConstantValue);
2394 else
2395 return new ImageStoreTestInstance(context, m_texture, m_format, m_tiling, m_declareImageFormatInShader,
2396 m_singleLayerBind, m_minalign, m_storeConstantValue);
2397 }
2398
createInstance(Context & context) const2399 TestInstance *LoadStoreTest::createInstance(Context &context) const
2400 {
2401 if (m_imageLoadStoreLodAMD)
2402 return new ImageLoadStoreLodAMDTestInstance(context, m_texture, m_format, m_imageFormat,
2403 m_declareFormatInShaderReads, m_singleLayerBind, m_minalign,
2404 m_bufferLoadUniform);
2405
2406 if (m_texture.type() == IMAGE_TYPE_BUFFER)
2407 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat,
2408 m_declareFormatInShaderReads, m_minalign, m_bufferLoadUniform);
2409 else
2410 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_tiling,
2411 m_declareFormatInShaderReads, m_singleLayerBind, m_minalign,
2412 m_bufferLoadUniform);
2413 }
2414
2415 class ImageExtendOperandTestInstance : public BaseTestInstance
2416 {
2417 public:
2418 ImageExtendOperandTestInstance(Context &context, const Texture &texture, const VkFormat readFormat,
2419 const VkFormat writeFormat, bool relaxedPrecision);
2420
~ImageExtendOperandTestInstance(void)2421 virtual ~ImageExtendOperandTestInstance(void)
2422 {
2423 }
2424
2425 protected:
2426 VkDescriptorSetLayout prepareDescriptors(void);
2427 void commandBeforeCompute(const VkCommandBuffer cmdBuffer);
2428 void commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer);
2429 void commandAfterCompute(const VkCommandBuffer cmdBuffer);
2430
2431 void commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout,
2432 const int layerNdx);
2433
2434 tcu::TestStatus verifyResult(void);
2435
2436 protected:
2437 bool m_isSigned;
2438 tcu::TextureLevel m_inputImageData;
2439
2440 de::MovePtr<Image> m_imageSrc; // source image
2441 SharedVkImageView m_imageSrcView;
2442 VkDeviceSize m_imageSrcSize;
2443
2444 de::MovePtr<Image> m_imageDst; // dest image
2445 SharedVkImageView m_imageDstView;
2446 VkFormat m_imageDstFormat;
2447 VkDeviceSize m_imageDstSize;
2448
2449 de::MovePtr<BufferWithMemory> m_buffer; // result buffer
2450
2451 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2452 Move<VkDescriptorPool> m_descriptorPool;
2453 SharedVkDescriptorSet m_descriptorSet;
2454
2455 bool m_relaxedPrecision;
2456 };
2457
ImageExtendOperandTestInstance(Context & context,const Texture & texture,const VkFormat readFormat,const VkFormat writeFormat,bool relaxedPrecision)2458 ImageExtendOperandTestInstance::ImageExtendOperandTestInstance(Context &context, const Texture &texture,
2459 const VkFormat readFormat, const VkFormat writeFormat,
2460 bool relaxedPrecision)
2461 : BaseTestInstance(context, texture, readFormat, true, true, false, false)
2462 , m_imageDstFormat(writeFormat)
2463 , m_relaxedPrecision(relaxedPrecision)
2464 {
2465 const DeviceInterface &vk = m_context.getDeviceInterface();
2466 const VkDevice device = m_context.getDevice();
2467 Allocator &allocator = m_context.getDefaultAllocator();
2468 const int32_t width = texture.size().x();
2469 const int32_t height = texture.size().y();
2470 const tcu::TextureFormat textureFormat = mapVkFormat(m_format);
2471
2472 // Generate reference image
2473 m_isSigned = (getTextureChannelClass(textureFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2474 m_inputImageData.setStorage(textureFormat, width, height, 1);
2475
2476 const tcu::PixelBufferAccess access = m_inputImageData.getAccess();
2477 const int valueStart = (m_isSigned ? (-width / 2) : 0);
2478
2479 for (int x = 0; x < width; ++x)
2480 for (int y = 0; y < height; ++y)
2481 {
2482 const tcu::IVec4 color(valueStart + x, valueStart + y, valueStart, valueStart);
2483 access.setPixel(color, x, y);
2484 }
2485
2486 // Create source image
2487 m_imageSrc = de::MovePtr<Image>(new Image(
2488 vk, device, allocator,
2489 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0u),
2490 MemoryRequirement::Any));
2491
2492 // Create destination image
2493 m_imageDst = de::MovePtr<Image>(
2494 new Image(vk, device, allocator,
2495 makeImageCreateInfo(m_texture, m_imageDstFormat,
2496 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
2497 MemoryRequirement::Any));
2498
2499 // Compute image and buffer sizes
2500 m_imageSrcSize = width * height * tcu::getPixelSize(textureFormat);
2501 m_imageDstSize = width * height * tcu::getPixelSize(mapVkFormat(m_imageDstFormat));
2502 VkDeviceSize bufferSizeBytes = de::max(m_imageSrcSize, m_imageDstSize);
2503
2504 // Create helper buffer able to store input data and image write result
2505 m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
2506 vk, device, allocator,
2507 makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
2508 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
2509 MemoryRequirement::HostVisible));
2510
2511 const Allocation &alloc = m_buffer->getAllocation();
2512 deMemcpy(alloc.getHostPtr(), m_inputImageData.getAccess().getDataPtr(), static_cast<size_t>(m_imageSrcSize));
2513 flushAlloc(vk, device, alloc);
2514 }
2515
prepareDescriptors(void)2516 VkDescriptorSetLayout ImageExtendOperandTestInstance::prepareDescriptors(void)
2517 {
2518 const DeviceInterface &vk = m_context.getDeviceInterface();
2519 const VkDevice device = m_context.getDevice();
2520
2521 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2522 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2523 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2524 .build(vk, device);
2525
2526 m_descriptorPool = DescriptorPoolBuilder()
2527 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2528 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2529 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
2530
2531 const VkImageViewType viewType = mapImageViewType(m_texture.type());
2532 const VkImageSubresourceRange subresourceRange =
2533 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2534
2535 m_descriptorSet = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
2536 m_imageSrcView =
2537 makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
2538 m_imageDstView =
2539 makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_imageDstFormat, subresourceRange));
2540
2541 return *m_descriptorSetLayout; // not passing the ownership
2542 }
2543
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)2544 void ImageExtendOperandTestInstance::commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,
2545 const VkPipelineLayout pipelineLayout,
2546 const int layerNdx)
2547 {
2548 DE_UNREF(layerNdx);
2549
2550 const DeviceInterface &vk = m_context.getDeviceInterface();
2551 const VkDevice device = m_context.getDevice();
2552 const VkDescriptorSet descriptorSet = **m_descriptorSet;
2553
2554 const VkDescriptorImageInfo descriptorSrcImageInfo =
2555 makeDescriptorImageInfo(VK_NULL_HANDLE, **m_imageSrcView, VK_IMAGE_LAYOUT_GENERAL);
2556 const VkDescriptorImageInfo descriptorDstImageInfo =
2557 makeDescriptorImageInfo(VK_NULL_HANDLE, **m_imageDstView, VK_IMAGE_LAYOUT_GENERAL);
2558
2559 typedef DescriptorSetUpdateBuilder::Location DSUBL;
2560 DescriptorSetUpdateBuilder()
2561 .writeSingle(descriptorSet, DSUBL::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
2562 .writeSingle(descriptorSet, DSUBL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
2563 .update(vk, device);
2564 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u,
2565 nullptr);
2566 }
2567
commandBeforeCompute(const VkCommandBuffer cmdBuffer)2568 void ImageExtendOperandTestInstance::commandBeforeCompute(const VkCommandBuffer cmdBuffer)
2569 {
2570 const DeviceInterface &vk = m_context.getDeviceInterface();
2571
2572 const VkImageSubresourceRange fullImageSubresourceRange =
2573 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
2574 {
2575 const VkImageMemoryBarrier preCopyImageBarriers[] = {
2576 makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2577 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_imageSrc->get(), fullImageSubresourceRange),
2578 makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
2579 m_imageDst->get(), fullImageSubresourceRange)};
2580
2581 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
2582 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, m_buffer->get(), 0ull, m_imageSrcSize);
2583
2584 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
2585 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
2586 (VkDependencyFlags)0, 0, nullptr, 1, &barrierFlushHostWriteBeforeCopy,
2587 DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
2588 }
2589 {
2590 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
2591 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2592 VK_IMAGE_LAYOUT_GENERAL, m_imageSrc->get(), fullImageSubresourceRange);
2593
2594 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
2595
2596 vk.cmdCopyBufferToImage(cmdBuffer, m_buffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u,
2597 ©Region);
2598 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2599 (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &barrierAfterCopy);
2600 }
2601 }
2602
commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)2603 void ImageExtendOperandTestInstance::commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)
2604 {
2605 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
2606 }
2607
commandAfterCompute(const VkCommandBuffer cmdBuffer)2608 void ImageExtendOperandTestInstance::commandAfterCompute(const VkCommandBuffer cmdBuffer)
2609 {
2610 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_buffer->get(), m_imageDstSize, m_texture);
2611 }
2612
2613 // Clears the high bits of every pixel in the pixel buffer, leaving only the lowest 16 bits of each component.
clearHighBits(const tcu::PixelBufferAccess & pixels,int width,int height)2614 void clearHighBits(const tcu::PixelBufferAccess &pixels, int width, int height)
2615 {
2616 for (int y = 0; y < height; ++y)
2617 for (int x = 0; x < width; ++x)
2618 {
2619 auto color = pixels.getPixelUint(x, y);
2620 for (int c = 0; c < decltype(color)::SIZE; ++c)
2621 color[c] &= 0xFFFFull;
2622 pixels.setPixel(color, x, y);
2623 }
2624 }
2625
verifyResult(void)2626 tcu::TestStatus ImageExtendOperandTestInstance::verifyResult(void)
2627 {
2628 const DeviceInterface &vk = m_context.getDeviceInterface();
2629 const VkDevice device = m_context.getDevice();
2630 const tcu::IVec3 imageSize = m_texture.size();
2631 const tcu::PixelBufferAccess inputAccess = m_inputImageData.getAccess();
2632 const int32_t width = inputAccess.getWidth();
2633 const int32_t height = inputAccess.getHeight();
2634 tcu::TextureLevel refImage(mapVkFormat(m_imageDstFormat), width, height);
2635 tcu::PixelBufferAccess refAccess = refImage.getAccess();
2636
2637 for (int x = 0; x < width; ++x)
2638 for (int y = 0; y < height; ++y)
2639 {
2640 tcu::IVec4 color = inputAccess.getPixelInt(x, y);
2641 refAccess.setPixel(color, x, y);
2642 }
2643
2644 const Allocation &alloc = m_buffer->getAllocation();
2645 invalidateAlloc(vk, device, alloc);
2646 const tcu::PixelBufferAccess result(mapVkFormat(m_imageDstFormat), imageSize, alloc.getHostPtr());
2647
2648 if (m_relaxedPrecision)
2649 {
2650 // Preserve the lowest 16 bits of the reference and result pixels only.
2651 clearHighBits(refAccess, width, height);
2652 clearHighBits(result, width, height);
2653 }
2654
2655 if (tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Comparison", "Comparison", refAccess, result,
2656 tcu::UVec4(0), tcu::COMPARE_LOG_RESULT, true /*use64Bits*/))
2657 return tcu::TestStatus::pass("Passed");
2658 else
2659 return tcu::TestStatus::fail("Image comparison failed");
2660 }
2661
2662 enum class ExtendTestType
2663 {
2664 READ = 0,
2665 WRITE,
2666 WRITE_NONTEMPORAL,
2667 };
2668
2669 enum class ExtendOperand
2670 {
2671 SIGN_EXTEND = 0,
2672 ZERO_EXTEND = 1
2673 };
2674
2675 class ImageExtendOperandTest : public TestCase
2676 {
2677 public:
2678 ImageExtendOperandTest(tcu::TestContext &testCtx, const std::string &name, const Texture texture,
2679 const VkFormat readFormat, const VkFormat writeFormat, const bool signedInt,
2680 const bool relaxedPrecision, ExtendTestType extendTestType);
2681
2682 void checkSupport(Context &context) const;
2683 void initPrograms(SourceCollections &programCollection) const;
2684 TestInstance *createInstance(Context &context) const;
2685
2686 private:
isWriteTest() const2687 bool isWriteTest() const
2688 {
2689 return (m_extendTestType == ExtendTestType::WRITE) || (m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL);
2690 }
2691
2692 const Texture m_texture;
2693 VkFormat m_readFormat;
2694 VkFormat m_writeFormat;
2695 bool m_operandForce; // Use an operand that doesn't match SampledType?
2696 bool m_relaxedPrecision;
2697 ExtendTestType m_extendTestType;
2698 };
2699
ImageExtendOperandTest(tcu::TestContext & testCtx,const std::string & name,const Texture texture,const VkFormat readFormat,const VkFormat writeFormat,const bool operandForce,const bool relaxedPrecision,ExtendTestType extendTestType)2700 ImageExtendOperandTest::ImageExtendOperandTest(tcu::TestContext &testCtx, const std::string &name,
2701 const Texture texture, const VkFormat readFormat,
2702 const VkFormat writeFormat, const bool operandForce,
2703 const bool relaxedPrecision, ExtendTestType extendTestType)
2704 : TestCase(testCtx, name)
2705 , m_texture(texture)
2706 , m_readFormat(readFormat)
2707 , m_writeFormat(writeFormat)
2708 , m_operandForce(operandForce)
2709 , m_relaxedPrecision(relaxedPrecision)
2710 , m_extendTestType(extendTestType)
2711 {
2712 }
2713
checkFormatProperties(const Context & context,VkFormat format)2714 void checkFormatProperties(const Context &context, VkFormat format)
2715 {
2716 #ifndef CTS_USES_VULKANSC
2717 const VkFormatProperties3 formatProperties(context.getFormatProperties(format));
2718
2719 if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2720 TCU_THROW(NotSupportedError, "Format not supported for storage images");
2721 #else
2722 const VkFormatProperties formatProperties(
2723 getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), format));
2724
2725 if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2726 TCU_THROW(NotSupportedError, "Format not supported for storage images");
2727 #endif // CTS_USES_VULKANSC
2728 }
2729
check64BitSupportIfNeeded(Context & context,VkFormat readFormat,VkFormat writeFormat)2730 void check64BitSupportIfNeeded(Context &context, VkFormat readFormat, VkFormat writeFormat)
2731 {
2732 if (is64BitIntegerFormat(readFormat) || is64BitIntegerFormat(writeFormat))
2733 {
2734 const auto &features = context.getDeviceFeatures();
2735 if (!features.shaderInt64)
2736 TCU_THROW(NotSupportedError, "64-bit integers not supported in shaders");
2737 }
2738 }
2739
checkSupport(Context & context) const2740 void ImageExtendOperandTest::checkSupport(Context &context) const
2741 {
2742 if (!context.requireDeviceFunctionality("VK_KHR_spirv_1_4"))
2743 TCU_THROW(NotSupportedError, "VK_KHR_spirv_1_4 not supported");
2744
2745 #ifndef CTS_USES_VULKANSC
2746 DE_ASSERT(m_readFormat != VK_FORMAT_A8_UNORM_KHR && m_writeFormat != VK_FORMAT_A8_UNORM_KHR);
2747 DE_ASSERT(m_readFormat != VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR &&
2748 m_writeFormat != VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR);
2749
2750 if ((m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL) && (context.getUsedApiVersion() < VK_API_VERSION_1_3))
2751 TCU_THROW(NotSupportedError, "Vulkan 1.3 or higher is required for this test to run");
2752 #endif // CTS_USES_VULKANSC
2753
2754 check64BitSupportIfNeeded(context, m_readFormat, m_writeFormat);
2755
2756 checkFormatProperties(context, m_readFormat);
2757 checkFormatProperties(context, m_writeFormat);
2758 }
2759
initPrograms(SourceCollections & programCollection) const2760 void ImageExtendOperandTest::initPrograms(SourceCollections &programCollection) const
2761 {
2762 tcu::StringTemplate shaderTemplate(
2763 "OpCapability Shader\n"
2764 "OpCapability StorageImageExtendedFormats\n"
2765
2766 "${capability}"
2767 "${extension}"
2768
2769 "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
2770 "OpMemoryModel Logical GLSL450\n"
2771 "OpEntryPoint GLCompute %main \"main\" %id %src_image_ptr %dst_image_ptr\n"
2772 "OpExecutionMode %main LocalSize 1 1 1\n"
2773
2774 // decorations
2775 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2776
2777 "OpDecorate %src_image_ptr DescriptorSet 0\n"
2778 "OpDecorate %src_image_ptr Binding 0\n"
2779 "OpDecorate %src_image_ptr NonWritable\n"
2780
2781 "${relaxed_precision}"
2782
2783 "OpDecorate %dst_image_ptr DescriptorSet 0\n"
2784 "OpDecorate %dst_image_ptr Binding 1\n"
2785 "OpDecorate %dst_image_ptr NonReadable\n"
2786
2787 // types
2788 "%type_void = OpTypeVoid\n"
2789 "%type_i32 = OpTypeInt 32 1\n"
2790 "%type_u32 = OpTypeInt 32 0\n"
2791 "%type_vec2_i32 = OpTypeVector %type_i32 2\n"
2792 "%type_vec2_u32 = OpTypeVector %type_u32 2\n"
2793 "%type_vec3_i32 = OpTypeVector %type_i32 3\n"
2794 "%type_vec3_u32 = OpTypeVector %type_u32 3\n"
2795 "%type_vec4_i32 = OpTypeVector %type_i32 4\n"
2796 "%type_vec4_u32 = OpTypeVector %type_u32 4\n"
2797 "${extra_types}"
2798
2799 "%type_fun_void = OpTypeFunction %type_void\n"
2800
2801 "${image_types}"
2802
2803 "%type_ptr_in_vec3_u32 = OpTypePointer Input %type_vec3_u32\n"
2804 "%type_ptr_in_u32 = OpTypePointer Input %type_u32\n"
2805
2806 "${image_uniforms}"
2807
2808 // variables
2809 "%id = OpVariable %type_ptr_in_vec3_u32 Input\n"
2810
2811 "${image_variables}"
2812
2813 // main function
2814 "%main = OpFunction %type_void None %type_fun_void\n"
2815 "%label = OpLabel\n"
2816
2817 "${image_load}"
2818
2819 "%idvec = OpLoad %type_vec3_u32 %id\n"
2820 "%id_xy = OpVectorShuffle %type_vec2_u32 %idvec %idvec 0 1\n"
2821 "%coord = OpBitcast %type_vec2_i32 %id_xy\n"
2822 "%value = OpImageRead ${sampled_type_vec4} %src_image %coord "
2823 "${read_extend_operand}\n"
2824 " OpImageWrite %dst_image %coord %value ${write_extend_operand}\n"
2825 " OpReturn\n"
2826 " OpFunctionEnd\n");
2827
2828 const auto testedFormat = mapVkFormat(isWriteTest() ? m_writeFormat : m_readFormat);
2829 const bool isSigned = (getTextureChannelClass(testedFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2830
2831 const auto isRead64 = is64BitIntegerFormat(m_readFormat);
2832 const auto isWrite64 = is64BitIntegerFormat(m_writeFormat);
2833 DE_ASSERT(isRead64 == isWrite64);
2834
2835 const bool using64Bits = (isRead64 || isWrite64);
2836
2837 // Additional capabilities when needed.
2838 std::string capability;
2839 std::string extension;
2840 std::string extraTypes;
2841
2842 if (using64Bits)
2843 {
2844 extension += "OpExtension \"SPV_EXT_shader_image_int64\"\n";
2845 capability += "OpCapability Int64\n"
2846 "OpCapability Int64ImageEXT\n";
2847 extraTypes += "%type_i64 = OpTypeInt 64 1\n"
2848 "%type_u64 = OpTypeInt 64 0\n"
2849 "%type_vec3_i64 = OpTypeVector %type_i64 3\n"
2850 "%type_vec3_u64 = OpTypeVector %type_u64 3\n"
2851 "%type_vec4_i64 = OpTypeVector %type_i64 4\n"
2852 "%type_vec4_u64 = OpTypeVector %type_u64 4\n";
2853 }
2854
2855 std::string relaxed = "";
2856 if (m_relaxedPrecision)
2857 relaxed += "OpDecorate %src_image_ptr RelaxedPrecision\n";
2858
2859 // Sampled type depends on the format sign and mismatch force flag.
2860 const bool signedSampleType = ((isSigned && !m_operandForce) || (!isSigned && m_operandForce));
2861 const std::string bits = (using64Bits ? "64" : "32");
2862 const std::string sampledTypePostfix = (signedSampleType ? "i" : "u") + bits;
2863 const std::string extendOperandStr = (isSigned ? "SignExtend" : "ZeroExtend");
2864
2865 std::map<std::string, std::string> specializations{
2866 {"image_type_id", "%type_image"},
2867 {"image_uni_ptr_type_id", "%type_ptr_uniform_const_image"},
2868 {"image_var_id", "%src_image_ptr"},
2869 {"image_id", "%src_image"},
2870 {"capability", capability},
2871 {"extension", extension},
2872 {"extra_types", extraTypes},
2873 {"relaxed_precision", relaxed},
2874 {"image_format", getSpirvFormat(m_readFormat)},
2875 {"sampled_type", (std::string("%type_") + sampledTypePostfix)},
2876 {"sampled_type_vec4", (std::string("%type_vec4_") + sampledTypePostfix)},
2877 {"read_extend_operand", (!isWriteTest() ? extendOperandStr : "")},
2878 {"write_extend_operand", (isWriteTest() ? extendOperandStr : "")},
2879 };
2880
2881 SpirvVersion spirvVersion = SPIRV_VERSION_1_4;
2882 bool allowSpirv14 = true;
2883 if (m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL)
2884 {
2885 spirvVersion = SPIRV_VERSION_1_6;
2886 allowSpirv14 = false;
2887 specializations["write_extend_operand"] = "Nontemporal";
2888 }
2889
2890 // Addidtional parametrization is needed for a case when source and destination textures have same format
2891 tcu::StringTemplate imageTypeTemplate(
2892 "${image_type_id} = OpTypeImage ${sampled_type} 2D 0 0 0 2 ${image_format}\n");
2893 tcu::StringTemplate imageUniformTypeTemplate(
2894 "${image_uni_ptr_type_id} = OpTypePointer UniformConstant ${image_type_id}\n");
2895 tcu::StringTemplate imageVariablesTemplate(
2896 "${image_var_id} = OpVariable ${image_uni_ptr_type_id} UniformConstant\n");
2897 tcu::StringTemplate imageLoadTemplate(
2898 "${image_id} = OpLoad ${image_type_id} ${image_var_id}\n");
2899
2900 std::string imageTypes;
2901 std::string imageUniformTypes;
2902 std::string imageVariables;
2903 std::string imageLoad;
2904
2905 // If input image format is the same as output there is less spir-v definitions
2906 if (m_readFormat == m_writeFormat)
2907 {
2908 imageTypes = imageTypeTemplate.specialize(specializations);
2909 imageUniformTypes = imageUniformTypeTemplate.specialize(specializations);
2910 imageVariables = imageVariablesTemplate.specialize(specializations);
2911 imageLoad = imageLoadTemplate.specialize(specializations);
2912
2913 specializations["image_var_id"] = "%dst_image_ptr";
2914 specializations["image_id"] = "%dst_image";
2915 imageVariables += imageVariablesTemplate.specialize(specializations);
2916 imageLoad += imageLoadTemplate.specialize(specializations);
2917 }
2918 else
2919 {
2920 specializations["image_type_id"] = "%type_src_image";
2921 specializations["image_uni_ptr_type_id"] = "%type_ptr_uniform_const_src_image";
2922 imageTypes = imageTypeTemplate.specialize(specializations);
2923 imageUniformTypes = imageUniformTypeTemplate.specialize(specializations);
2924 imageVariables = imageVariablesTemplate.specialize(specializations);
2925 imageLoad = imageLoadTemplate.specialize(specializations);
2926
2927 specializations["image_format"] = getSpirvFormat(m_writeFormat);
2928 specializations["image_type_id"] = "%type_dst_image";
2929 specializations["image_uni_ptr_type_id"] = "%type_ptr_uniform_const_dst_image";
2930 specializations["image_var_id"] = "%dst_image_ptr";
2931 specializations["image_id"] = "%dst_image";
2932 imageTypes += imageTypeTemplate.specialize(specializations);
2933 imageUniformTypes += imageUniformTypeTemplate.specialize(specializations);
2934 imageVariables += imageVariablesTemplate.specialize(specializations);
2935 imageLoad += imageLoadTemplate.specialize(specializations);
2936 }
2937
2938 specializations["image_types"] = imageTypes;
2939 specializations["image_uniforms"] = imageUniformTypes;
2940 specializations["image_variables"] = imageVariables;
2941 specializations["image_load"] = imageLoad;
2942
2943 // Specialize whole shader and add it to program collection
2944 programCollection.spirvAsmSources.add("comp")
2945 << shaderTemplate.specialize(specializations)
2946 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, spirvVersion, allowSpirv14);
2947 }
2948
createInstance(Context & context) const2949 TestInstance *ImageExtendOperandTest::createInstance(Context &context) const
2950 {
2951 return new ImageExtendOperandTestInstance(context, m_texture, m_readFormat, m_writeFormat, m_relaxedPrecision);
2952 }
2953
2954 static const Texture s_textures[] = {
2955 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1),
2956 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8),
2957 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1),
2958 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8),
2959 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1),
2960 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6),
2961 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2 * 6),
2962 Texture(IMAGE_TYPE_BUFFER, tcu::IVec3(64, 1, 1), 1),
2963 };
2964
getTestTexture(const ImageType imageType)2965 const Texture &getTestTexture(const ImageType imageType)
2966 {
2967 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2968 if (s_textures[textureNdx].type() == imageType)
2969 return s_textures[textureNdx];
2970
2971 DE_FATAL("Internal error");
2972 return s_textures[0];
2973 }
2974
2975 static const VkFormat s_formats[] = {VK_FORMAT_R32G32B32A32_SFLOAT,
2976 VK_FORMAT_R16G16B16A16_SFLOAT,
2977 VK_FORMAT_R32_SFLOAT,
2978
2979 VK_FORMAT_R32G32B32A32_UINT,
2980 VK_FORMAT_R16G16B16A16_UINT,
2981 VK_FORMAT_R8G8B8A8_UINT,
2982 VK_FORMAT_R32_UINT,
2983
2984 VK_FORMAT_R32G32B32A32_SINT,
2985 VK_FORMAT_R16G16B16A16_SINT,
2986 VK_FORMAT_R8G8B8A8_SINT,
2987 VK_FORMAT_R32_SINT,
2988
2989 VK_FORMAT_R8G8B8A8_UNORM,
2990
2991 VK_FORMAT_B8G8R8A8_UNORM,
2992 VK_FORMAT_B8G8R8A8_UINT,
2993
2994 VK_FORMAT_R8G8B8A8_SNORM,
2995
2996 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2997
2998 VK_FORMAT_R32G32_SFLOAT,
2999 VK_FORMAT_R16G16_SFLOAT,
3000 VK_FORMAT_R16_SFLOAT,
3001
3002 VK_FORMAT_A2B10G10R10_UINT_PACK32,
3003 VK_FORMAT_R32G32_UINT,
3004 VK_FORMAT_R16G16_UINT,
3005 VK_FORMAT_R16_UINT,
3006 VK_FORMAT_R8G8_UINT,
3007 VK_FORMAT_R8_UINT,
3008
3009 VK_FORMAT_R32G32_SINT,
3010 VK_FORMAT_R16G16_SINT,
3011 VK_FORMAT_R16_SINT,
3012 VK_FORMAT_R8G8_SINT,
3013 VK_FORMAT_R8_SINT,
3014
3015 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3016 VK_FORMAT_R16G16B16A16_UNORM,
3017 VK_FORMAT_R16G16B16A16_SNORM,
3018 VK_FORMAT_R16G16_UNORM,
3019 VK_FORMAT_R16_UNORM,
3020 VK_FORMAT_R8G8_UNORM,
3021 VK_FORMAT_R8_UNORM,
3022 #ifndef CTS_USES_VULKANSC
3023 VK_FORMAT_A8_UNORM_KHR,
3024 #endif // CTS_USES_VULKANSC
3025
3026 VK_FORMAT_R16G16_SNORM,
3027 VK_FORMAT_R16_SNORM,
3028 VK_FORMAT_R8G8_SNORM,
3029 VK_FORMAT_R8_SNORM,
3030
3031 VK_FORMAT_R10X6_UNORM_PACK16,
3032 VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
3033 VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
3034
3035 VK_FORMAT_R4G4_UNORM_PACK8,
3036 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
3037 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
3038 VK_FORMAT_R5G6B5_UNORM_PACK16,
3039 VK_FORMAT_B5G6R5_UNORM_PACK16,
3040 VK_FORMAT_R5G5B5A1_UNORM_PACK16,
3041 VK_FORMAT_B5G5R5A1_UNORM_PACK16,
3042 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
3043 #ifndef CTS_USES_VULKANSC
3044 VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
3045 #endif // CTS_USES_VULKANSC
3046
3047 VK_FORMAT_B8G8R8A8_SNORM,
3048 VK_FORMAT_B8G8R8A8_SINT,
3049 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
3050 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
3051 VK_FORMAT_A8B8G8R8_UINT_PACK32,
3052 VK_FORMAT_A8B8G8R8_SINT_PACK32,
3053 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3054 VK_FORMAT_A2R10G10B10_SNORM_PACK32,
3055 VK_FORMAT_A2R10G10B10_UINT_PACK32,
3056 VK_FORMAT_A2R10G10B10_SINT_PACK32,
3057 VK_FORMAT_A2B10G10R10_SNORM_PACK32,
3058 VK_FORMAT_A2B10G10R10_SINT_PACK32,
3059 VK_FORMAT_R32G32B32_UINT,
3060 VK_FORMAT_R32G32B32_SINT,
3061 VK_FORMAT_R32G32B32_SFLOAT,
3062 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
3063
3064 VK_FORMAT_R8G8_SRGB,
3065 VK_FORMAT_R8G8B8_SRGB,
3066 VK_FORMAT_B8G8R8_SRGB,
3067 VK_FORMAT_R8G8B8A8_SRGB,
3068 VK_FORMAT_B8G8R8A8_SRGB,
3069 VK_FORMAT_A8B8G8R8_SRGB_PACK32};
3070
3071 static const VkFormat s_formatsThreeComponent[] = {
3072 VK_FORMAT_R8G8B8_UINT, VK_FORMAT_R8G8B8_SINT, VK_FORMAT_R8G8B8_UNORM, VK_FORMAT_R8G8B8_SNORM,
3073 VK_FORMAT_R16G16B16_UINT, VK_FORMAT_R16G16B16_SINT, VK_FORMAT_R16G16B16_UNORM, VK_FORMAT_R16G16B16_SNORM,
3074 VK_FORMAT_R16G16B16_SFLOAT, VK_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32_SINT, VK_FORMAT_R32G32B32_SFLOAT,
3075 };
3076
3077 static const VkFormat d_formats[] = {VK_FORMAT_D16_UNORM, VK_FORMAT_D32_SFLOAT};
3078
3079 static const VkImageTiling s_tilings[] = {
3080 VK_IMAGE_TILING_OPTIMAL,
3081 VK_IMAGE_TILING_LINEAR,
3082 };
3083
tilingSuffix(VkImageTiling tiling)3084 const char *tilingSuffix(VkImageTiling tiling)
3085 {
3086 switch (tiling)
3087 {
3088 case VK_IMAGE_TILING_OPTIMAL:
3089 return "";
3090 case VK_IMAGE_TILING_LINEAR:
3091 return "_linear";
3092 default:
3093 return "unknown";
3094 }
3095 }
3096
isAllowedDepthFormat(const Texture & texture,VkFormat format,const VkImageTiling tiling)3097 bool isAllowedDepthFormat(const Texture &texture, VkFormat format, const VkImageTiling tiling)
3098 {
3099 if (isDepthStencilFormat(format) && (tiling == VK_IMAGE_TILING_OPTIMAL) &&
3100 ((texture.type() == IMAGE_TYPE_2D) || (texture.type() == IMAGE_TYPE_2D_ARRAY)))
3101 {
3102 return true;
3103 }
3104 return false;
3105 }
3106
3107 // m_testType == TC_COMP_COMP
3108 // First compute shader executes that will flip the input image, image0, horizontally in output image, image1.
3109 // First compute shader makes image1 available in the shader domain with device scope barrier.
3110 // Pipeline barrier executes that adds execution dependency: second shader will only execute after the first has completed.
3111 // Then second compute shader executes making image1 visible in the shader domain and copies image1 back to image0 without any change.
3112 // image0 is compared to the reference output that should be flipped horizontally.
3113 //
3114 // m_testType == TC_COMP_DRAW
3115 // First compute shader executes that will flip the input image, image0, horizontally in output image, image1.
3116 // First compute shader makes image1 available in the shader domain with device scope barrier.
3117 // Pipeline barrier executes that adds execution dependency: second shader will only execute after first has completed.
3118 // Then vertex shader executes and it does not change the image.
3119 // Fragment compute shader executes making image1 visible in the shader domain and copies image1 to a color attachment without any change.
3120 // color attachment is compared to the reference output that should be flipped horizontally.
3121 class ImageDeviceScopeAccessTest : public LoadStoreTest
3122 {
3123 public:
3124 ImageDeviceScopeAccessTest(tcu::TestContext &testCtx, const TestConfigurationType testType, const std::string &name,
3125 const Texture &texture, const VkFormat format, const VkImageTiling tiling);
3126 void checkSupport(Context &context) const;
3127 void initPrograms(SourceCollections &sourceCollections) const;
3128 TestInstance *createInstance(Context &context) const;
3129
3130 private:
3131 const TestConfigurationType m_testType;
3132 const uint32_t m_verticesCount;
3133 };
3134
3135 class ImageDeviceScopeAccessTestInstance : public ImageLoadStoreTestInstance
3136 {
3137 public:
3138 ImageDeviceScopeAccessTestInstance(Context &context, const TestConfigurationType testType, const Texture &texture,
3139 const VkFormat format, const VkImageTiling tiling, const uint32_t verticesCount);
3140
3141 tcu::TestStatus iterate(void);
3142
3143 private:
3144 const TestConfigurationType m_testType;
3145 const VkImageTiling m_tiling;
3146 const uint32_t m_verticesCount;
3147 };
3148
ImageDeviceScopeAccessTest(tcu::TestContext & testCtx,const TestConfigurationType testType,const std::string & name,const Texture & texture,const VkFormat format,const VkImageTiling tiling)3149 ImageDeviceScopeAccessTest::ImageDeviceScopeAccessTest(tcu::TestContext &testCtx, const TestConfigurationType testType,
3150 const std::string &name, const Texture &texture,
3151 const VkFormat format, const VkImageTiling tiling)
3152 : LoadStoreTest(testCtx, name, texture, format, format, tiling)
3153 , m_testType(testType)
3154 , m_verticesCount(6u)
3155 {
3156 DE_ASSERT(texture.numLayers() == 1u);
3157 DE_ASSERT(m_singleLayerBind == false);
3158 DE_ASSERT(m_restrictImages == false);
3159 DE_ASSERT(m_minalign == false);
3160 DE_ASSERT(m_bufferLoadUniform == false);
3161 DE_ASSERT(m_imageLoadStoreLodAMD == false);
3162 }
3163
initPrograms(SourceCollections & sourceCollections) const3164 void ImageDeviceScopeAccessTest::initPrograms(SourceCollections &sourceCollections) const
3165 {
3166 makePrograms(sourceCollections, DEVICESCOPE_STORE);
3167 makePrograms(sourceCollections, DEVICESCOPE_LOAD, (m_testType == TC_COMP_DRAW), m_verticesCount);
3168 }
3169
checkSupport(Context & context) const3170 void ImageDeviceScopeAccessTest::checkSupport(Context &context) const
3171 {
3172 if (!context.contextSupports(vk::ApiVersion(0, 1, 1, 0)))
3173 TCU_THROW(NotSupportedError, "Vulkan 1.1 not supported");
3174
3175 VkPhysicalDeviceVulkanMemoryModelFeatures vkMemModelFeatures = context.getVulkanMemoryModelFeatures();
3176 if (!vkMemModelFeatures.vulkanMemoryModel)
3177 TCU_THROW(NotSupportedError, "vulkanMemoryModel not supported");
3178
3179 if (!vkMemModelFeatures.vulkanMemoryModelDeviceScope)
3180 TCU_THROW(NotSupportedError, "vulkanMemoryModelDeviceScope not supported");
3181
3182 if (context.getUsedApiVersion() < SPIRV_VERSION_1_5)
3183 TCU_THROW(NotSupportedError,
3184 std::string("Vulkan higher than or equal to spirv 1.5 is required for this test to run").c_str());
3185
3186 if ((m_testType == TC_COMP_DRAW) && context.getTestContext().getCommandLine().isComputeOnly())
3187 THROW_NOT_SUPPORTED_COMPUTE_ONLY();
3188
3189 LoadStoreTest::checkSupport(context);
3190
3191 if (m_testType == TC_COMP_DRAW)
3192 {
3193 const auto &vki = context.getInstanceInterface();
3194 const auto physicalDevice = context.getPhysicalDevice();
3195
3196 VkImageFormatProperties vkImageFormatProperties;
3197 const auto result = vki.getPhysicalDeviceImageFormatProperties(
3198 physicalDevice, m_format, mapImageType(m_texture.type()), m_tiling,
3199 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0, &vkImageFormatProperties);
3200
3201 if (result != VK_SUCCESS)
3202 {
3203 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
3204 TCU_THROW(NotSupportedError, "Format unsupported for tiling");
3205 else
3206 TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned unexpected error");
3207 }
3208 }
3209 }
3210
createInstance(Context & context) const3211 TestInstance *ImageDeviceScopeAccessTest::createInstance(Context &context) const
3212 {
3213 return new ImageDeviceScopeAccessTestInstance(context, m_testType, m_texture, m_format, m_tiling, m_verticesCount);
3214 }
3215
ImageDeviceScopeAccessTestInstance(Context & context,const TestConfigurationType testType,const Texture & texture,const VkFormat format,const VkImageTiling tiling,const uint32_t verticesCount)3216 ImageDeviceScopeAccessTestInstance::ImageDeviceScopeAccessTestInstance(Context &context,
3217 const TestConfigurationType testType,
3218 const Texture &texture, const VkFormat format,
3219 const VkImageTiling tiling,
3220 const uint32_t verticesCount)
3221 : ImageLoadStoreTestInstance(context, texture, format, format, tiling, true, false, false, false)
3222 , m_testType(testType)
3223 , m_tiling(tiling)
3224 , m_verticesCount(verticesCount)
3225 {
3226 }
3227
iterate(void)3228 tcu::TestStatus ImageDeviceScopeAccessTestInstance::iterate(void)
3229 {
3230 const DeviceInterface &vk = m_context.getDeviceInterface();
3231 const VkDevice device = m_context.getDevice();
3232 const VkQueue queue = m_context.getUniversalQueue();
3233 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
3234 Allocator &allocator = m_context.getDefaultAllocator();
3235 const tcu::IVec3 workSize = m_texture.size();
3236
3237 Move<VkShaderModule> shaderModuleLoad;
3238 Move<VkPipeline> pipelineLoad;
3239
3240 // Variables for draw call
3241 Move<VkShaderModule> shaderModuleVert;
3242 Move<VkRenderPass> renderPass;
3243 de::MovePtr<Image> colorAttachmentImage;
3244 Move<VkImageView> colorAttachment;
3245 Move<VkFramebuffer> framebuffer;
3246
3247 const Unique<VkShaderModule> shaderModuleStore(
3248 createShaderModule(vk, device, m_context.getBinaryCollection().get("comp_store")));
3249
3250 VkShaderStageFlags descriptorStageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
3251 if (m_testType == TC_COMP_DRAW)
3252 descriptorStageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT;
3253 const VkDescriptorSetLayout descriptorSetLayout = commonPrepareDescriptors(descriptorStageFlags);
3254 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
3255 const Unique<VkPipeline> pipelineStore(makeComputePipeline(vk, device, *pipelineLayout, *shaderModuleStore));
3256
3257 const Unique<VkCommandPool> cmdPool(
3258 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
3259 const Unique<VkCommandBuffer> cmdBuffer(
3260 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3261
3262 beginCommandBuffer(vk, *cmdBuffer);
3263
3264 // First compute shader that loads reference image and copies to another image
3265 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineStore);
3266
3267 commandBeforeCompute(*cmdBuffer);
3268
3269 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, 0u);
3270
3271 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
3272
3273 // Barrier between shaders/pipelines
3274 const VkImageSubresourceRange subresourceRange =
3275 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
3276 const VkImageMemoryBarrier imageBarrierBetweenShaders =
3277 makeImageMemoryBarrier(VK_ACCESS_2_NONE, VK_ACCESS_2_NONE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
3278 m_imageSrc->get(), subresourceRange);
3279 const VkPipelineStageFlags dstStageMask =
3280 (m_testType == TC_COMP_DRAW) ? (VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) :
3281 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
3282 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, dstStageMask, (VkDependencyFlags)0, 0,
3283 nullptr, 0, nullptr, 1, &imageBarrierBetweenShaders);
3284
3285 // Switch to the second shader program
3286
3287 if (m_testType == TC_COMP_DRAW)
3288 {
3289 shaderModuleVert = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"));
3290 shaderModuleLoad = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"));
3291
3292 renderPass = makeRenderPass(vk, device, m_format);
3293
3294 const uint32_t colorAttachmentCount = 1u;
3295
3296 colorAttachmentImage = de::MovePtr<Image>(new Image(
3297 vk, device, allocator,
3298 makeImageCreateInfo(m_texture, m_format,
3299 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, m_tiling),
3300 MemoryRequirement::Any));
3301
3302 colorAttachment =
3303 makeImageView(vk, device, colorAttachmentImage->get(), mapImageViewType(m_texture.type()), m_format,
3304 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers()));
3305
3306 const VkExtent2D extent = makeExtent2D(m_texture.size().x(), m_texture.size().y());
3307
3308 const VkFramebufferCreateInfo fbCreateInfo = {
3309 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType
3310 nullptr, // const void* pNext
3311 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
3312 *renderPass, // VkRenderPass renderPass
3313 colorAttachmentCount, // uint32_t attachmentCount
3314 &*colorAttachment, // const VkImageView* pAttachments
3315 extent.width, // uint32_t width
3316 extent.height, // uint32_t height
3317 1u // uint32_t layers
3318 };
3319 framebuffer = createFramebuffer(vk, device, &fbCreateInfo);
3320
3321 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
3322 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
3323 nullptr, // const void* pNext
3324 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags
3325 0u, // uint32_t vertexBindingDescriptionCount
3326 nullptr, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
3327 0u, // uint32_t vertexAttributeDescriptionCount
3328 nullptr // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
3329 };
3330
3331 const VkViewport viewport = makeViewport(extent.width, extent.height);
3332 const VkRect2D scissor = makeRect2D(extent.width, extent.height);
3333
3334 const VkPipelineViewportStateCreateInfo viewportStateCreateInfo = {
3335 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
3336 nullptr, // const void* pNext
3337 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
3338 1u, // uint32_t viewportCount
3339 &viewport, // const VkViewport* pViewports
3340 1u, // uint32_t scissorCount
3341 &scissor // const VkRect2D* pScissors
3342 };
3343 pipelineLoad =
3344 vk::makeGraphicsPipeline(vk, device, *pipelineLayout, *shaderModuleVert, VK_NULL_HANDLE, VK_NULL_HANDLE,
3345 VK_NULL_HANDLE, *shaderModuleLoad, *renderPass, 0u, &vertexInputStateCreateInfo,
3346 nullptr, nullptr, &viewportStateCreateInfo);
3347
3348 const tcu::Vec4 clearColor(0.0f, 1.0f, 0.0f, 1.0f);
3349 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, extent.width, extent.height),
3350 clearColor);
3351
3352 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLoad);
3353
3354 const uint32_t layerNdx = 0u;
3355 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
3356 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet,
3357 0u, nullptr);
3358
3359 vk.cmdDraw(*cmdBuffer, m_verticesCount, 1u, 0u, 0u);
3360
3361 endRenderPass(vk, *cmdBuffer);
3362
3363 copyImageToBuffer(vk, *cmdBuffer, colorAttachmentImage->get(), m_imageBuffer->get(),
3364 tcu::IVec2(extent.width, extent.height));
3365 }
3366 else
3367 {
3368 shaderModuleLoad = createShaderModule(vk, device, m_context.getBinaryCollection().get("comp_load"));
3369
3370 pipelineLoad = makeComputePipeline(vk, device, *pipelineLayout, *shaderModuleLoad);
3371
3372 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLoad);
3373
3374 // descriptors already bound to command buffer on first dispatch
3375 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
3376
3377 const VkImageAspectFlags &aspectMask = getImageAspect(m_format);
3378 commandCopyImageToBuffer(m_context, *cmdBuffer, m_imageSrc->get(), m_imageBuffer->get(), m_imageSizeBytes,
3379 m_texture, aspectMask);
3380 }
3381
3382 endCommandBuffer(vk, *cmdBuffer);
3383 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3384
3385 return verifyResult();
3386 }
3387 } // namespace
3388
createImageStoreTests(tcu::TestContext & testCtx)3389 tcu::TestCaseGroup *createImageStoreTests(tcu::TestContext &testCtx)
3390 {
3391 // Plain imageStore() cases
3392 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store"));
3393 // Declare a format layout qualifier for write images
3394 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format"));
3395 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format"));
3396
3397 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
3398 {
3399 const Texture &texture = s_textures[textureNdx];
3400 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType(
3401 new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
3402 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType(
3403 new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
3404 const bool isLayered = (texture.numLayers() > 1);
3405
3406 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
3407 {
3408 for (int tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(s_tilings); tilingNdx++)
3409 {
3410 const bool hasSpirvFmt = hasSpirvFormat(s_formats[formatNdx]);
3411 const char *suffix = tilingSuffix(s_tilings[tilingNdx]);
3412
3413 if (hasSpirvFmt)
3414 {
3415 groupWithFormatByImageViewType->addChild(
3416 new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + suffix, texture,
3417 s_formats[formatNdx], s_tilings[tilingNdx]));
3418 // Additional tests where the shader uses constant data for imageStore.
3419 groupWithFormatByImageViewType->addChild(new StoreTest(
3420 testCtx, getFormatShortString(s_formats[formatNdx]) + "_constant" + suffix, texture,
3421 s_formats[formatNdx], s_tilings[tilingNdx],
3422 StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER | StoreTest::FLAG_STORE_CONSTANT_VALUE));
3423 }
3424 groupWithoutFormatByImageViewType->addChild(
3425 new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + suffix, texture,
3426 s_formats[formatNdx], s_tilings[tilingNdx], 0));
3427
3428 if (isLayered && hasSpirvFmt)
3429 groupWithFormatByImageViewType->addChild(new StoreTest(
3430 testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer" + suffix, texture,
3431 s_formats[formatNdx], VK_IMAGE_TILING_OPTIMAL,
3432 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
3433
3434 if (texture.type() == IMAGE_TYPE_BUFFER)
3435 {
3436 if (hasSpirvFmt)
3437 groupWithFormatByImageViewType->addChild(
3438 new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign" + suffix,
3439 texture, s_formats[formatNdx], s_tilings[tilingNdx],
3440 StoreTest::FLAG_MINALIGN | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
3441 groupWithoutFormatByImageViewType->addChild(
3442 new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign" + suffix,
3443 texture, s_formats[formatNdx], s_tilings[tilingNdx], StoreTest::FLAG_MINALIGN));
3444 }
3445 }
3446 }
3447
3448 {
3449 // Test depth formats with storage image
3450
3451 // Depth formats for storage images are only allowed with optimal tiling
3452 const auto testTilingType = VK_IMAGE_TILING_OPTIMAL;
3453
3454 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(d_formats); ++formatNdx)
3455 {
3456 const char *suffix = tilingSuffix(testTilingType);
3457 const auto testFormat = d_formats[formatNdx];
3458 const auto formatShortString = getFormatShortString(testFormat);
3459
3460 if (!isAllowedDepthFormat(texture, testFormat, testTilingType))
3461 continue;
3462
3463 groupWithoutFormatByImageViewType->addChild(
3464 new StoreTest(testCtx, formatShortString + suffix, texture, testFormat, testTilingType, 0));
3465
3466 #if 0
3467 /* 'with_format' tests require format declaration in shader.
3468 Since depth format has no spirv equivalent, r16 can be used for d16 and r32f can be used for d32_sfloat.
3469 The validation layers do not complain and it works on some implementations */
3470
3471 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, formatShortString + suffix, texture, testFormat, testTilingType));
3472 // Additional tests where the shader uses constant data for imageStore.
3473 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, formatShortString + "_constant" + suffix, texture, testFormat, testTilingType, StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER | StoreTest::FLAG_STORE_CONSTANT_VALUE));
3474
3475 if (isLayered)
3476 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, formatShortString + "_single_layer" + suffix,
3477 texture, testFormat, testTilingType,
3478 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
3479 #endif
3480 }
3481 }
3482
3483 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
3484 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
3485 }
3486
3487 testGroup->addChild(testGroupWithFormat.release());
3488 testGroup->addChild(testGroupWithoutFormat.release());
3489
3490 return testGroup.release();
3491 }
3492
createImageLoadStoreTests(tcu::TestContext & testCtx)3493 tcu::TestCaseGroup *createImageLoadStoreTests(tcu::TestContext &testCtx)
3494 {
3495 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store"));
3496 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format"));
3497 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format"));
3498 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutAnyFormat(new tcu::TestCaseGroup(testCtx, "without_any_format"));
3499
3500 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
3501 {
3502 const Texture &texture = s_textures[textureNdx];
3503 const auto imageTypeName = getImageTypeName(texture.type());
3504 const bool isLayered = (texture.numLayers() > 1);
3505
3506 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType(
3507 new tcu::TestCaseGroup(testCtx, imageTypeName.c_str()));
3508 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType(
3509 new tcu::TestCaseGroup(testCtx, imageTypeName.c_str()));
3510 de::MovePtr<tcu::TestCaseGroup> groupWithoutAnyFormatByImageViewType(
3511 new tcu::TestCaseGroup(testCtx, imageTypeName.c_str()));
3512
3513 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
3514 {
3515 const auto formatShortString = getFormatShortString(s_formats[formatNdx]);
3516 const auto hasSpvFormat = hasSpirvFormat(s_formats[formatNdx]);
3517
3518 for (int tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(s_tilings); tilingNdx++)
3519 {
3520 const char *suffix = tilingSuffix(s_tilings[tilingNdx]);
3521
3522 if (hasSpvFormat)
3523 {
3524 groupWithFormatByImageViewType->addChild(
3525 new LoadStoreTest(testCtx, formatShortString + suffix, texture, s_formats[formatNdx],
3526 s_formats[formatNdx], s_tilings[tilingNdx]));
3527 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(
3528 testCtx, formatShortString + suffix, texture, s_formats[formatNdx], s_formats[formatNdx],
3529 s_tilings[tilingNdx], LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3530 }
3531
3532 groupWithoutAnyFormatByImageViewType->addChild(
3533 new LoadStoreTest(testCtx, formatShortString + suffix, texture, s_formats[formatNdx],
3534 s_formats[formatNdx], s_tilings[tilingNdx], 0u));
3535
3536 if (isLayered && hasSpvFormat)
3537 groupWithFormatByImageViewType->addChild(new LoadStoreTest(
3538 testCtx, formatShortString + "_single_layer" + suffix, texture, s_formats[formatNdx],
3539 s_formats[formatNdx], s_tilings[tilingNdx],
3540 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS |
3541 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3542
3543 if (texture.type() == IMAGE_TYPE_BUFFER)
3544 {
3545 if (hasSpvFormat)
3546 {
3547 groupWithFormatByImageViewType->addChild(new LoadStoreTest(
3548 testCtx, formatShortString + "_minalign" + suffix, texture, s_formats[formatNdx],
3549 s_formats[formatNdx], s_tilings[tilingNdx],
3550 LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS |
3551 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3552 groupWithFormatByImageViewType->addChild(new LoadStoreTest(
3553 testCtx, formatShortString + "_minalign_uniform" + suffix, texture, s_formats[formatNdx],
3554 s_formats[formatNdx], s_tilings[tilingNdx],
3555 LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS |
3556 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES |
3557 LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
3558 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(
3559 testCtx, formatShortString + "_minalign" + suffix, texture, s_formats[formatNdx],
3560 s_formats[formatNdx], s_tilings[tilingNdx],
3561 LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3562 groupWithoutFormatByImageViewType->addChild(
3563 new LoadStoreTest(testCtx, formatShortString + "_minalign_uniform" + suffix, texture,
3564 s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx],
3565 LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER |
3566 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3567 }
3568 groupWithoutAnyFormatByImageViewType->addChild(new LoadStoreTest(
3569 testCtx, formatShortString + "_minalign" + suffix, texture, s_formats[formatNdx],
3570 s_formats[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_MINALIGN));
3571 groupWithoutAnyFormatByImageViewType->addChild(
3572 new LoadStoreTest(testCtx, formatShortString + "_minalign_uniform" + suffix, texture,
3573 s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx],
3574 LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
3575 }
3576 }
3577 }
3578
3579 if (texture.type() == IMAGE_TYPE_BUFFER)
3580 {
3581 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formatsThreeComponent); ++formatNdx)
3582 {
3583 const auto formatShortString = getFormatShortString(s_formatsThreeComponent[formatNdx]);
3584
3585 for (int tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(s_tilings); tilingNdx++)
3586 {
3587 const char *suffix = tilingSuffix(s_tilings[tilingNdx]);
3588
3589 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(
3590 testCtx, formatShortString + "_uniform" + suffix, texture, s_formatsThreeComponent[formatNdx],
3591 s_formatsThreeComponent[formatNdx], s_tilings[tilingNdx],
3592 LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER |
3593 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3594 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(
3595 testCtx, formatShortString + "_minalign_uniform" + suffix, texture,
3596 s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], s_tilings[tilingNdx],
3597 LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER |
3598 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3599 }
3600 }
3601 }
3602
3603 {
3604 // Test depth formats with storage image
3605
3606 // Depth formats for storage images are only allowed with optimal tiling
3607 const auto testTilingType = VK_IMAGE_TILING_OPTIMAL;
3608
3609 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(d_formats); ++formatNdx)
3610 {
3611 const char *suffix = tilingSuffix(testTilingType);
3612 const auto testFormat = d_formats[formatNdx];
3613 const auto formatShortString = getFormatShortString(testFormat);
3614
3615 if (!isAllowedDepthFormat(texture, testFormat, testTilingType))
3616 continue;
3617
3618 groupWithoutAnyFormatByImageViewType->addChild(new LoadStoreTest(
3619 testCtx, formatShortString + suffix, texture, testFormat, testFormat, testTilingType, 0u));
3620 #if 0
3621 /* 'with_format' tests and tests that have FLAG_DECLARE_FORMAT_IN_SHADER_* flags require format declaration in shader.
3622 Since depth format has no spirv equivalent, r16 can be used for d16 and r32f can be used for d32_sfloat.
3623 The validation layers do not complain and it works on some implementations */
3624
3625 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + suffix, texture, testFormat, testFormat, testTilingType));
3626 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + suffix, texture, testFormat, testFormat, testTilingType, LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3627
3628 if (isLayered)
3629 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_single_layer" + suffix,
3630 texture, s_formats[formatNdx], s_formats[formatNdx], testTilingType,
3631 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3632 #endif
3633 }
3634 }
3635
3636 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
3637 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
3638 testGroupWithoutAnyFormat->addChild(groupWithoutAnyFormatByImageViewType.release());
3639 }
3640
3641 testGroup->addChild(testGroupWithFormat.release());
3642 testGroup->addChild(testGroupWithoutFormat.release());
3643 testGroup->addChild(testGroupWithoutAnyFormat.release());
3644
3645 return testGroup.release();
3646 }
3647
createImageLoadStoreLodAMDTests(tcu::TestContext & testCtx)3648 tcu::TestCaseGroup *createImageLoadStoreLodAMDTests(tcu::TestContext &testCtx)
3649 {
3650 static const Texture textures[] = {
3651 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8, 1, 6),
3652 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1, 1, 6),
3653 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1, 1, 6),
3654 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8, 1, 6),
3655 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1, 1, 6),
3656 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6, 1, 6),
3657 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2 * 6, 1, 6),
3658 };
3659
3660 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_lod"));
3661 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format"));
3662 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format"));
3663
3664 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(textures); ++textureNdx)
3665 {
3666 const Texture &texture = textures[textureNdx];
3667 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType(
3668 new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
3669 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType(
3670 new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
3671 const bool isLayered = (texture.numLayers() > 1);
3672
3673 if (texture.type() == IMAGE_TYPE_BUFFER)
3674 continue;
3675
3676 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
3677 {
3678 // These tests always require a SPIR-V format for the write image, even if the read
3679 // image is being used without a format.
3680 if (!hasSpirvFormat(s_formats[formatNdx]))
3681 continue;
3682
3683 groupWithFormatByImageViewType->addChild(
3684 new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), texture, s_formats[formatNdx],
3685 s_formats[formatNdx], VK_IMAGE_TILING_OPTIMAL,
3686 (LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS |
3687 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES),
3688 true));
3689 groupWithoutFormatByImageViewType->addChild(
3690 new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), texture, s_formats[formatNdx],
3691 s_formats[formatNdx], VK_IMAGE_TILING_OPTIMAL,
3692 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES, true));
3693
3694 if (isLayered)
3695 groupWithFormatByImageViewType->addChild(new LoadStoreTest(
3696 testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", texture,
3697 s_formats[formatNdx], s_formats[formatNdx], VK_IMAGE_TILING_OPTIMAL,
3698 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS |
3699 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES,
3700 true));
3701 }
3702
3703 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
3704 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
3705 }
3706
3707 testGroup->addChild(testGroupWithFormat.release());
3708 testGroup->addChild(testGroupWithoutFormat.release());
3709
3710 return testGroup.release();
3711 }
3712
createImageFormatReinterpretTests(tcu::TestContext & testCtx)3713 tcu::TestCaseGroup *createImageFormatReinterpretTests(tcu::TestContext &testCtx)
3714 {
3715 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret"));
3716
3717 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
3718 {
3719 const Texture &texture = s_textures[textureNdx];
3720 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType(
3721 new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
3722
3723 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
3724 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
3725 {
3726 if (!hasSpirvFormat(s_formats[formatNdx]))
3727 continue;
3728
3729 const std::string caseName =
3730 getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
3731 if (imageFormatNdx != formatNdx &&
3732 formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
3733 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, texture, s_formats[formatNdx],
3734 s_formats[imageFormatNdx],
3735 VK_IMAGE_TILING_OPTIMAL));
3736 }
3737 testGroup->addChild(groupByImageViewType.release());
3738 }
3739
3740 return testGroup.release();
3741 }
3742
createImageQualifierRestrictCase(tcu::TestContext & testCtx,const ImageType imageType,const std::string & name)3743 de::MovePtr<TestCase> createImageQualifierRestrictCase(tcu::TestContext &testCtx, const ImageType imageType,
3744 const std::string &name)
3745 {
3746 const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
3747 const Texture &texture = getTestTexture(imageType);
3748 return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, texture, format, format, VK_IMAGE_TILING_OPTIMAL,
3749 LoadStoreTest::FLAG_RESTRICT_IMAGES |
3750 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS |
3751 LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3752 }
3753
3754 namespace
3755 {
3756
relaxedOK(VkFormat format)3757 bool relaxedOK(VkFormat format)
3758 {
3759 tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(format));
3760 int maxBitDepth = deMax32(deMax32(bitDepth[0], bitDepth[1]), deMax32(bitDepth[2], bitDepth[3]));
3761 return maxBitDepth <= 16;
3762 }
3763
3764 // Get a format used for reading or writing in extension operand tests. These formats allow representing the shader sampled type to
3765 // verify results from read or write operations.
getShaderExtensionOperandFormat(bool isSigned,bool is64Bit)3766 VkFormat getShaderExtensionOperandFormat(bool isSigned, bool is64Bit)
3767 {
3768 const VkFormat formats[] = {
3769 VK_FORMAT_R32G32B32A32_UINT,
3770 VK_FORMAT_R32G32B32A32_SINT,
3771 VK_FORMAT_R64_UINT,
3772 VK_FORMAT_R64_SINT,
3773 };
3774 return formats[2u * (is64Bit ? 1u : 0u) + (isSigned ? 1u : 0u)];
3775 }
3776
3777 // INT or UINT format?
isIntegralFormat(VkFormat format)3778 bool isIntegralFormat(VkFormat format)
3779 {
3780 return (isIntFormat(format) || isUintFormat(format));
3781 }
3782
3783 // Return the list of formats used for the extension operand tests (SignExten/ZeroExtend).
getExtensionOperandFormatList(void)3784 std::vector<VkFormat> getExtensionOperandFormatList(void)
3785 {
3786 std::vector<VkFormat> formatList;
3787
3788 for (auto format : s_formats)
3789 {
3790 if (isIntegralFormat(format))
3791 formatList.push_back(format);
3792 }
3793
3794 formatList.push_back(VK_FORMAT_R64_SINT);
3795 formatList.push_back(VK_FORMAT_R64_UINT);
3796
3797 return formatList;
3798 }
3799
3800 } // namespace
3801
createImageExtendOperandsTests(tcu::TestContext & testCtx)3802 tcu::TestCaseGroup *createImageExtendOperandsTests(tcu::TestContext &testCtx)
3803 {
3804 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
3805
3806 GroupPtr testGroup(new tcu::TestCaseGroup(testCtx, "extend_operands_spirv1p4"));
3807
3808 const struct
3809 {
3810 ExtendTestType testType;
3811 const char *name;
3812 } testTypes[] = {
3813 {ExtendTestType::READ, "read"},
3814 {ExtendTestType::WRITE, "write"},
3815 };
3816
3817 const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
3818 const auto formatList = getExtensionOperandFormatList();
3819
3820 for (const auto format : formatList)
3821 {
3822 const auto isInt = isIntFormat(format);
3823 const auto isUint = isUintFormat(format);
3824 const auto use64Bits = is64BitIntegerFormat(format);
3825
3826 DE_ASSERT(isInt || isUint);
3827
3828 GroupPtr formatGroup(new tcu::TestCaseGroup(testCtx, getFormatShortString(format).c_str()));
3829
3830 for (const auto &testType : testTypes)
3831 {
3832 GroupPtr testTypeGroup(new tcu::TestCaseGroup(testCtx, testType.name));
3833
3834 for (int match = 0; match < 2; ++match)
3835 {
3836 const bool mismatched = (match == 1);
3837 const char *matchGroupName = (mismatched ? "mismatched_sign" : "matched_sign");
3838
3839 // SPIR-V does not allow this kind of sampled type override.
3840 if (mismatched && isUint)
3841 continue;
3842
3843 GroupPtr matchGroup(new tcu::TestCaseGroup(testCtx, matchGroupName));
3844
3845 for (int prec = 0; prec < 2; prec++)
3846 {
3847 const bool relaxedPrecision = (prec != 0);
3848
3849 const char *precisionName = (relaxedPrecision ? "relaxed_precision" : "normal_precision");
3850 const auto signedOther = ((isInt && !mismatched) || (isUint && mismatched));
3851 const auto otherFormat = getShaderExtensionOperandFormat(signedOther, use64Bits);
3852 const auto readFormat = (testType.testType == ExtendTestType::READ ? format : otherFormat);
3853 const auto writeFormat = (testType.testType == ExtendTestType::WRITE ? format : otherFormat);
3854
3855 if (relaxedPrecision && !relaxedOK(readFormat))
3856 continue;
3857
3858 if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
3859 continue;
3860
3861 matchGroup->addChild(new ImageExtendOperandTest(testCtx, precisionName, texture, readFormat,
3862 writeFormat, mismatched, relaxedPrecision,
3863 testType.testType));
3864 }
3865
3866 testTypeGroup->addChild(matchGroup.release());
3867 }
3868
3869 formatGroup->addChild(testTypeGroup.release());
3870 }
3871
3872 testGroup->addChild(formatGroup.release());
3873 }
3874
3875 return testGroup.release();
3876 }
3877
createImageNontemporalOperandTests(tcu::TestContext & testCtx)3878 tcu::TestCaseGroup *createImageNontemporalOperandTests(tcu::TestContext &testCtx)
3879 {
3880 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "nontemporal_operand"));
3881
3882 const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
3883
3884 // using just integer formats for tests so that ImageExtendOperandTest could be reused
3885 const auto formatList = getExtensionOperandFormatList();
3886
3887 for (const auto format : formatList)
3888 {
3889 const std::string caseName = getFormatShortString(format);
3890 const auto readFormat = format;
3891 const auto writeFormat = getShaderExtensionOperandFormat(isIntFormat(format), is64BitIntegerFormat(format));
3892
3893 if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
3894 continue;
3895
3896 // note: just testing OpImageWrite as OpImageRead is tested with addComputeImageSamplerTest
3897 testGroup->addChild(new ImageExtendOperandTest(testCtx, caseName, texture, readFormat, writeFormat, false,
3898 false, ExtendTestType::WRITE_NONTEMPORAL));
3899 }
3900
3901 return testGroup.release();
3902 }
3903
createImageDeviceScopeAccessTests(tcu::TestContext & testCtx)3904 tcu::TestCaseGroup *createImageDeviceScopeAccessTests(tcu::TestContext &testCtx)
3905 {
3906 const Texture testTextures[] = {
3907 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1),
3908 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1),
3909 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1, 1, 1),
3910 };
3911
3912 const struct TestConfiguration
3913 {
3914 TestConfigurationType type;
3915 const std::string typeName;
3916
3917 } testConfigurations[] = {{TC_COMP_COMP, "comp_comp"}, {TC_COMP_DRAW, "comp_draw"}};
3918
3919 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "device_scope_access"));
3920
3921 for (const auto &testConfig : testConfigurations)
3922 {
3923 de::MovePtr<tcu::TestCaseGroup> groupTestType(new tcu::TestCaseGroup(testCtx, testConfig.typeName.c_str()));
3924
3925 for (uint32_t textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(testTextures); ++textureNdx)
3926 {
3927 const Texture &texture = testTextures[textureNdx];
3928 const auto imageTypeName = getImageTypeName(texture.type());
3929
3930 if ((testConfig.type == TC_COMP_DRAW) && (testTextures[textureNdx].type() == IMAGE_TYPE_3D))
3931 continue;
3932
3933 de::MovePtr<tcu::TestCaseGroup> groupImageType(new tcu::TestCaseGroup(testCtx, imageTypeName.c_str()));
3934
3935 for (uint32_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
3936 {
3937 const auto formatShortString = getFormatShortString(s_formats[formatNdx]);
3938 const auto hasSpvFormat = hasSpirvFormat(s_formats[formatNdx]);
3939
3940 for (uint32_t tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(s_tilings); tilingNdx++)
3941 {
3942 const char *suffix = tilingSuffix(s_tilings[tilingNdx]);
3943
3944 if (hasSpvFormat)
3945 {
3946 groupImageType->addChild(
3947 new ImageDeviceScopeAccessTest(testCtx, testConfig.type, formatShortString + suffix,
3948 texture, s_formats[formatNdx], s_tilings[tilingNdx]));
3949 }
3950 }
3951 }
3952
3953 groupTestType->addChild(groupImageType.release());
3954 }
3955 testGroup->addChild(groupTestType.release());
3956 }
3957
3958 return testGroup.release();
3959 }
3960
3961 } // namespace image
3962 } // namespace vkt
3963