1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 The Android Open Source Project
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Image load/store Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktImageLoadStoreTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageLoadStoreUtil.hpp"
29 #include "vktImageTexture.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"
45 #include "deUniquePtr.hpp"
46 #include "deSharedPtr.hpp"
47 #include "deStringUtil.hpp"
49 #include "tcuImageCompare.hpp"
50 #include "tcuTexture.hpp"
51 #include "tcuTextureUtil.hpp"
52 #include "tcuFloat.hpp"
53 #include "tcuFloatFormat.hpp"
54 #include "tcuStringTemplate.hpp"
55 #include "tcuVectorUtil.hpp"
70 // Check for three-component (non-packed) format, i.e. pixel size is a multiple of 3.
71 bool formatHasThreeComponents(VkFormat format)
73 const tcu::TextureFormat texFormat = mapVkFormat(format);
74 return (getPixelSize(texFormat) % 3) == 0;
77 VkFormat getSingleComponentFormat(VkFormat format)
79 tcu::TextureFormat texFormat = mapVkFormat(format);
80 texFormat = tcu::TextureFormat(tcu::TextureFormat::R, texFormat.type);
81 return mapTextureFormat(texFormat);
84 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
86 return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
89 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
91 switch (texture.type())
95 case IMAGE_TYPE_BUFFER:
97 DE_ASSERT(layer == 0);
100 case IMAGE_TYPE_1D_ARRAY:
101 return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
103 case IMAGE_TYPE_2D_ARRAY:
104 case IMAGE_TYPE_CUBE:
105 case IMAGE_TYPE_CUBE_ARRAY:
106 case IMAGE_TYPE_3D: // 3d texture is treated as if depth was the layers
107 return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
110 DE_FATAL("Internal test error");
111 return tcu::ConstPixelBufferAccess();
115 //! \return the size in bytes of a given level of a mipmap image, including array layers.
116 vk::VkDeviceSize getMipmapLevelImageSizeBytes (const Texture& texture, const vk::VkFormat format, const deUint32 mipmapLevel)
118 tcu::IVec3 size = texture.size(mipmapLevel);
119 return tcu::getPixelSize(vk::mapVkFormat(format)) * size.x() * size.y() * size.z();
122 //! \return the size in bytes of the whole mipmap image, including all mipmap levels and array layers
123 vk::VkDeviceSize getMipmapImageTotalSizeBytes (const Texture& texture, const vk::VkFormat format)
125 vk::VkDeviceSize size = 0u;
126 deInt32 levelCount = 0u;
130 size += getMipmapLevelImageSizeBytes(texture, format, levelCount);
132 } while (levelCount < texture.numMipmapLevels());
136 //! \return true if all layers match in both pixel buffers
137 bool comparePixelBuffers (tcu::TestLog& log,
138 const Texture& texture,
139 const VkFormat format,
140 const tcu::ConstPixelBufferAccess reference,
141 const tcu::ConstPixelBufferAccess result,
142 const deUint32 mipmapLevel = 0u)
144 DE_ASSERT(reference.getFormat() == result.getFormat());
145 DE_ASSERT(reference.getSize() == result.getSize());
147 const bool is3d = (texture.type() == IMAGE_TYPE_3D);
148 const int numLayersOrSlices = (is3d ? texture.size(mipmapLevel).z() : texture.numLayers());
149 const int numCubeFaces = 6;
151 int passedLayers = 0;
152 for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
154 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
155 const std::string comparisonDesc = "Image Comparison, " +
156 (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
157 is3d ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx) + " , level " + de::toString(mipmapLevel));
159 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
160 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
164 switch (tcu::getTextureChannelClass(mapVkFormat(format).type))
166 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
167 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
169 ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
173 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
175 // Allow error of minimum representable difference
176 tcu::Vec4 threshold(1.0f / ((tcu::UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()) - 1u).cast<float>());
178 // Add 1 ULP of fp32 imprecision to account for image comparison fp32 math with unorm->float conversions.
179 threshold += tcu::Vec4(std::numeric_limits<float>::epsilon());
181 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
185 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
187 const tcu::UVec4 bitDepth = tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u;
188 // To avoid bit-shifting with negative value, which is undefined behaviour.
189 const tcu::UVec4 fixedBitDepth = tcu::select(bitDepth, tcu::UVec4(0u, 0u, 0u, 0u), tcu::greaterThanEqual(bitDepth.cast<deInt32>(), tcu::IVec4(0, 0, 0, 0)));
191 // Allow error of minimum representable difference
192 const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << fixedBitDepth) - 1u).cast<float>());
194 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
198 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
200 // Convert target format ulps to float ulps and allow 1 ulp difference
201 const tcu::UVec4 threshold (tcu::UVec4(1u) << (tcu::UVec4(23) - tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()));
203 ok = tcu::floatUlpThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
208 DE_FATAL("Unknown channel class");
215 return passedLayers == numLayersOrSlices;
218 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
219 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
221 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
223 for (int z = 0; z < access.getDepth(); ++z)
224 for (int y = 0; y < access.getHeight(); ++y)
225 for (int x = 0; x < access.getWidth(); ++x)
227 const tcu::Vec4 color(access.getPixel(x, y, z));
228 tcu::Vec4 newColor = color;
230 for (int i = 0; i < 4; ++i)
232 if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
234 const tcu::Float16 f(color[i]);
235 if (f.isDenorm() || f.isInf() || f.isNaN())
240 const tcu::Float32 f(color[i]);
241 if (f.isDenorm() || f.isInf() || f.isNaN())
246 if (newColor != color)
247 access.setPixel(newColor, x, y, z);
251 //!< replace invalid pixels in the image (-128)
252 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
254 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
256 for (int z = 0; z < access.getDepth(); ++z)
257 for (int y = 0; y < access.getHeight(); ++y)
258 for (int x = 0; x < access.getWidth(); ++x)
260 const tcu::IVec4 color(access.getPixelInt(x, y, z));
261 tcu::IVec4 newColor = color;
263 for (int i = 0; i < 4; ++i)
265 const deInt32 oldColor(color[i]);
266 if (oldColor == -128) newColor[i] = -127;
269 if (newColor != color)
270 access.setPixel(newColor, x, y, z);
274 tcu::Vec4 getMiddleValue(VkFormat imageFormat)
276 tcu::TextureFormat format = mapVkFormat(imageFormat);
277 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(format);
278 tcu::Vec4 val = (fmtInfo.valueMax - fmtInfo.valueMin) * tcu::Vec4(0.5f);
280 if (isIntegerFormat(imageFormat))
286 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat, bool constantValue = false)
288 // Generate a reference image data using the storage format
290 tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
291 const tcu::PixelBufferAccess access = reference.getAccess();
293 const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
294 const float storeColorBias = computeStoreColorBias(imageFormat);
296 const bool intFormat = isIntegerFormat(imageFormat);
297 const bool storeNegativeValues = isSignedFormat(imageFormat) && (storeColorBias == 0);
298 const int xMax = imageSize.x() - 1;
299 const int yMax = imageSize.y() - 1;
301 for (int z = 0; z < imageSize.z(); ++z)
302 for (int y = 0; y < imageSize.y(); ++y)
303 for (int x = 0; x < imageSize.x(); ++x)
307 access.setPixel(getMiddleValue(imageFormat), x, y, z);
311 tcu::IVec4 color = tcu::IVec4(x ^ y ^ z, (xMax - x) ^ y ^ z, x ^ (yMax - y) ^ z, (xMax - x) ^ (yMax - y) ^ z);
313 if (storeNegativeValues)
314 color -= tcu::IVec4(deRoundFloatToInt32((float)de::max(xMax, yMax) / 2.0f));
317 access.setPixel(color, x, y, z);
319 access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z);
323 // If the image is to be accessed as a float texture, get rid of invalid values
325 if (isFloatFormat(readFormat) && imageFormat != readFormat)
326 replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
327 if (isSnormFormat(readFormat) && imageFormat != readFormat)
328 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
333 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, bool constantValue = false)
335 return generateReferenceImage(imageSize, imageFormat, imageFormat, constantValue);
338 void flipHorizontally (const tcu::PixelBufferAccess access)
340 const int xMax = access.getWidth() - 1;
341 const int halfWidth = access.getWidth() / 2;
343 if (isIntegerFormat(mapTextureFormat(access.getFormat())))
344 for (int z = 0; z < access.getDepth(); z++)
345 for (int y = 0; y < access.getHeight(); y++)
346 for (int x = 0; x < halfWidth; x++)
348 const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
349 access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
350 access.setPixel(temp, x, y, z);
353 for (int z = 0; z < access.getDepth(); z++)
354 for (int y = 0; y < access.getHeight(); y++)
355 for (int x = 0; x < halfWidth; x++)
357 const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
358 access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
359 access.setPixel(temp, x, y, z);
363 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
365 return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
368 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
370 const DeviceInterface& vk = context.getDeviceInterface();
372 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
373 const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
374 VK_ACCESS_SHADER_WRITE_BIT, 0u,
375 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
376 image, fullImageSubresourceRange);
378 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier);
381 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
383 const DeviceInterface& vk = context.getDeviceInterface();
385 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
386 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
387 buffer, 0ull, bufferSizeBytes);
389 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
392 //! Copy all layers of an image to a buffer.
393 void commandCopyImageToBuffer (Context& context,
394 const VkCommandBuffer cmdBuffer,
396 const VkBuffer buffer,
397 const VkDeviceSize bufferSizeBytes,
398 const Texture& texture)
400 const DeviceInterface& vk = context.getDeviceInterface();
402 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
403 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
404 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
405 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
406 image, fullImageSubresourceRange);
408 const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
410 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
411 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
412 buffer, 0ull, bufferSizeBytes);
414 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier);
415 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ©Region);
416 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©Barrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
419 //! Copy all layers of a mipmap image to a buffer.
420 void commandCopyMipmapImageToBuffer (Context& context,
421 const VkCommandBuffer cmdBuffer,
423 const VkFormat imageFormat,
424 const VkBuffer buffer,
425 const VkDeviceSize bufferSizeBytes,
426 const Texture& texture)
428 const DeviceInterface& vk = context.getDeviceInterface();
430 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
431 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
432 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
433 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
434 image, fullImageSubresourceRange);
436 std::vector<VkBufferImageCopy> copyRegions;
437 VkDeviceSize bufferOffset = 0u;
438 for (deInt32 levelNdx = 0; levelNdx < texture.numMipmapLevels(); levelNdx++)
440 const VkBufferImageCopy copyParams =
442 bufferOffset, // VkDeviceSize bufferOffset;
443 0u, // deUint32 bufferRowLength;
444 0u, // deUint32 bufferImageHeight;
445 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
446 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
447 makeExtent3D(texture.layerSize(levelNdx)), // VkExtent3D imageExtent;
449 copyRegions.push_back(copyParams);
450 bufferOffset += getMipmapLevelImageSizeBytes(texture, imageFormat, levelNdx);
453 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
454 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
455 buffer, 0ull, bufferSizeBytes);
457 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier);
458 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, (deUint32) copyRegions.size(), copyRegions.data());
459 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©Barrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
462 class StoreTest : public TestCase
467 FLAG_SINGLE_LAYER_BIND = 0x1, //!< Run the shader multiple times, each time binding a different layer.
468 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 0x2, //!< Declare the format of the images in the shader code
469 FLAG_MINALIGN = 0x4, //!< Use bufferview offset that matches the advertised minimum alignment
470 FLAG_STORE_CONSTANT_VALUE = 0x8, //!< Store constant value
473 StoreTest (tcu::TestContext& testCtx,
474 const std::string& name,
475 const std::string& description,
476 const Texture& texture,
477 const VkFormat format,
478 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
480 virtual void checkSupport (Context& context) const;
481 void initPrograms (SourceCollections& programCollection) const;
482 TestInstance* createInstance (Context& context) const;
485 const Texture m_texture;
486 const VkFormat m_format;
487 const bool m_declareImageFormatInShader;
488 const bool m_singleLayerBind;
489 const bool m_minalign;
490 const bool m_storeConstantValue;
493 StoreTest::StoreTest (tcu::TestContext& testCtx,
494 const std::string& name,
495 const std::string& description,
496 const Texture& texture,
497 const VkFormat format,
498 const deUint32 flags)
499 : TestCase (testCtx, name, description)
500 , m_texture (texture)
502 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
503 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
504 , m_minalign ((flags & FLAG_MINALIGN) != 0)
505 , m_storeConstantValue ((flags & FLAG_STORE_CONSTANT_VALUE) != 0)
507 if (m_singleLayerBind)
508 DE_ASSERT(m_texture.numLayers() > 1);
511 void StoreTest::checkSupport (Context& context) const
513 #ifndef CTS_USES_VULKANSC
514 const VkFormatProperties3 formatProperties (context.getFormatProperties(m_format));
516 if (!m_declareImageFormatInShader && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
517 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage buffer");
519 if (!m_declareImageFormatInShader && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
520 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage images");
522 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
523 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
525 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
526 TCU_THROW(NotSupportedError, "Format not supported for storage images");
528 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
529 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
531 const VkFormatProperties formatProperties(getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_format));
533 if (!m_declareImageFormatInShader)
534 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
536 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
537 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
539 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
540 TCU_THROW(NotSupportedError, "Format not supported for storage images");
542 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
543 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
544 #endif // CTS_USES_VULKANSC
547 void StoreTest::initPrograms (SourceCollections& programCollection) const
549 const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
550 const float storeColorBias = computeStoreColorBias(m_format);
551 DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
553 const deUint32 xMax = m_texture.size().x() - 1;
554 const deUint32 yMax = m_texture.size().y() - 1;
555 const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
556 const bool storeNegativeValues = isSignedFormat(m_format) && (storeColorBias == 0);
557 bool useClamp = false;
558 std::string colorBaseExpr = signednessPrefix + "vec4(";
560 std::string colorExpr;
562 if (m_storeConstantValue)
564 tcu::Vec4 val = getMiddleValue(m_format);
566 if (isIntegerFormat(m_format))
568 colorExpr = colorBaseExpr
569 + de::toString(static_cast<deInt64>(val.x())) + ", "
570 + de::toString(static_cast<deInt64>(val.y())) + ", "
571 + de::toString(static_cast<deInt64>(val.z())) + ", "
572 + de::toString(static_cast<deInt64>(val.w())) + ")";
576 colorExpr = colorBaseExpr
577 + de::toString(val.x()) + ", "
578 + de::toString(val.y()) + ", "
579 + de::toString(val.z()) + ", "
580 + de::toString(val.w()) + ")";
585 colorBaseExpr = colorBaseExpr
587 + "(" + de::toString(xMax) + "-gx)^gy^gz, "
588 + "gx^(" + de::toString(yMax) + "-gy)^gz, "
589 + "(" + de::toString(xMax) + "-gx)^(" + de::toString(yMax) + "-gy)^gz)";
591 // Large integer values may not be represented with formats with low bit depths
592 if (isIntegerFormat(m_format))
594 const deInt64 minStoreValue = storeNegativeValues ? 0 - deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : 0;
595 const deInt64 maxStoreValue = storeNegativeValues ? deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : de::max(xMax, yMax);
597 useClamp = !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(minStoreValue), mapVkFormat(m_format)) ||
598 !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(maxStoreValue), mapVkFormat(m_format));
601 // Clamp if integer value cannot be represented with the current format
604 const tcu::IVec4 bitDepths = tcu::getTextureFormatBitDepth(mapVkFormat(m_format));
605 tcu::IVec4 minRepresentableValue;
606 tcu::IVec4 maxRepresentableValue;
608 switch (tcu::getTextureChannelClass(mapVkFormat(m_format).type))
610 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
612 minRepresentableValue = tcu::IVec4(0);
613 maxRepresentableValue = (tcu::IVec4(1) << bitDepths) - tcu::IVec4(1);
617 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
619 minRepresentableValue = -(tcu::IVec4(1) << bitDepths - tcu::IVec4(1));
620 maxRepresentableValue = (tcu::IVec4(1) << (bitDepths - tcu::IVec4(1))) - tcu::IVec4(1);
625 DE_ASSERT(isIntegerFormat(m_format));
628 colorBaseExpr = "clamp(" + colorBaseExpr + ", "
629 + signednessPrefix + "vec4" + de::toString(minRepresentableValue) + ", "
630 + signednessPrefix + "vec4" + de::toString(maxRepresentableValue) + ")";
633 colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
634 + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
636 if (storeNegativeValues)
637 colorExpr += "-" + de::toString(deRoundFloatToInt32((float)deMax32(xMax, yMax) / 2.0f));
640 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
641 const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
643 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
644 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
646 std::ostringstream src;
647 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
649 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
650 if (m_declareImageFormatInShader)
652 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
653 src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
656 src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n";
658 if (m_singleLayerBind)
659 src << "layout (binding = 1) readonly uniform Constants {\n"
660 << " int u_layerNdx;\n"
664 << "void main (void)\n"
666 << " int gx = int(gl_GlobalInvocationID.x);\n"
667 << " int gy = int(gl_GlobalInvocationID.y);\n"
668 << " int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
669 << " imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
672 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
675 //! Generic test iteration algorithm for image tests
676 class BaseTestInstance : public TestInstance
679 BaseTestInstance (Context& context,
680 const Texture& texture,
681 const VkFormat format,
682 const bool declareImageFormatInShader,
683 const bool singleLayerBind,
685 const bool bufferLoadUniform);
687 tcu::TestStatus iterate (void);
689 virtual ~BaseTestInstance (void) {}
692 virtual VkDescriptorSetLayout prepareDescriptors (void) = 0;
693 virtual tcu::TestStatus verifyResult (void) = 0;
695 virtual void commandBeforeCompute (const VkCommandBuffer cmdBuffer) = 0;
696 virtual void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer) = 0;
697 virtual void commandAfterCompute (const VkCommandBuffer cmdBuffer) = 0;
699 virtual void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
700 const VkPipelineLayout pipelineLayout,
701 const int layerNdx) = 0;
702 virtual deUint32 getViewOffset (Context& context,
703 const VkFormat format,
706 const Texture m_texture;
707 const VkFormat m_format;
708 const bool m_declareImageFormatInShader;
709 const bool m_singleLayerBind;
710 const bool m_minalign;
711 const bool m_bufferLoadUniform;
712 const deUint32 m_srcViewOffset;
713 const deUint32 m_dstViewOffset;
716 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign, const bool bufferLoadUniform)
717 : TestInstance (context)
718 , m_texture (texture)
720 , m_declareImageFormatInShader (declareImageFormatInShader)
721 , m_singleLayerBind (singleLayerBind)
722 , m_minalign (minalign)
723 , m_bufferLoadUniform (bufferLoadUniform)
724 , m_srcViewOffset (getViewOffset(context, format, m_bufferLoadUniform))
725 , m_dstViewOffset (getViewOffset(context, formatHasThreeComponents(format) ? getSingleComponentFormat(format) : format, false))
729 tcu::TestStatus BaseTestInstance::iterate (void)
731 const DeviceInterface& vk = m_context.getDeviceInterface();
732 const VkDevice device = m_context.getDevice();
733 const VkQueue queue = m_context.getUniversalQueue();
734 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
736 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
738 const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
739 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
740 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
742 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
743 const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
745 beginCommandBuffer(vk, *cmdBuffer);
747 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
748 commandBeforeCompute(*cmdBuffer);
750 const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
751 const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
752 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
754 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
757 commandBetweenShaderInvocations(*cmdBuffer);
759 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
762 commandAfterCompute(*cmdBuffer);
764 endCommandBuffer(vk, *cmdBuffer);
766 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
768 return verifyResult();
771 //! Base store test implementation
772 class StoreTestInstance : public BaseTestInstance
775 StoreTestInstance (Context& context,
776 const Texture& texture,
777 const VkFormat format,
778 const bool declareImageFormatInShader,
779 const bool singleLayerBind,
781 const bool storeConstantValue);
784 virtual tcu::TestStatus verifyResult (void);
786 // Add empty implementations for functions that might be not needed
787 void commandBeforeCompute (const VkCommandBuffer) {}
788 void commandBetweenShaderInvocations (const VkCommandBuffer) {}
789 void commandAfterCompute (const VkCommandBuffer) {}
791 de::MovePtr<Buffer> m_imageBuffer;
792 const VkDeviceSize m_imageSizeBytes;
793 bool m_storeConstantValue;
796 deUint32 BaseTestInstance::getViewOffset(Context& context,
797 const VkFormat format,
802 if (!context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
803 return (deUint32)context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
805 VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties;
806 deMemset(&alignmentProperties, 0, sizeof(alignmentProperties));
807 alignmentProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
809 VkPhysicalDeviceProperties2 properties2;
810 deMemset(&properties2, 0, sizeof(properties2));
811 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
812 properties2.pNext = &alignmentProperties;
814 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
816 VkBool32 singleTexelAlignment = uniform ? alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
817 alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
818 VkDeviceSize align = uniform ? alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
819 alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
821 VkDeviceSize texelSize = formatHasThreeComponents(format) ? tcu::getChannelSize(vk::mapVkFormat(format).type) : tcu::getPixelSize(vk::mapVkFormat(format));
823 if (singleTexelAlignment)
824 align = de::min(align, texelSize);
826 return (deUint32)align;
832 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign, const bool storeConstantValue)
833 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, false)
834 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format))
835 , m_storeConstantValue (storeConstantValue)
837 const DeviceInterface& vk = m_context.getDeviceInterface();
838 const VkDevice device = m_context.getDevice();
839 Allocator& allocator = m_context.getDefaultAllocator();
841 // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
843 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
844 vk, device, allocator,
845 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
846 MemoryRequirement::HostVisible));
849 tcu::TestStatus StoreTestInstance::verifyResult (void)
851 const DeviceInterface& vk = m_context.getDeviceInterface();
852 const VkDevice device = m_context.getDevice();
854 const tcu::IVec3 imageSize = m_texture.size();
855 const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format, m_storeConstantValue);
857 const Allocation& alloc = m_imageBuffer->getAllocation();
858 invalidateAlloc(vk, device, alloc);
859 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, (const char *)alloc.getHostPtr() + m_dstViewOffset);
861 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
862 return tcu::TestStatus::pass("Passed");
864 return tcu::TestStatus::fail("Image comparison failed");
867 //! Store test for images
868 class ImageStoreTestInstance : public StoreTestInstance
871 ImageStoreTestInstance (Context& context,
872 const Texture& texture,
873 const VkFormat format,
874 const bool declareImageFormatInShader,
875 const bool singleLayerBind,
877 const bool storeConstantValue);
880 VkDescriptorSetLayout prepareDescriptors (void);
881 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
882 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
883 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
885 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
886 const VkPipelineLayout pipelineLayout,
889 de::MovePtr<Image> m_image;
890 de::MovePtr<Buffer> m_constantsBuffer;
891 const VkDeviceSize m_constantsBufferChunkSizeBytes;
892 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
893 Move<VkDescriptorPool> m_descriptorPool;
894 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
895 std::vector<SharedVkImageView> m_allImageViews;
898 ImageStoreTestInstance::ImageStoreTestInstance (Context& context,
899 const Texture& texture,
900 const VkFormat format,
901 const bool declareImageFormatInShader,
902 const bool singleLayerBind,
904 const bool storeConstantValue)
905 : StoreTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, storeConstantValue)
906 , m_constantsBufferChunkSizeBytes (getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32)))
907 , m_allDescriptorSets (texture.numLayers())
908 , m_allImageViews (texture.numLayers())
910 const DeviceInterface& vk = m_context.getDeviceInterface();
911 const VkDevice device = m_context.getDevice();
912 Allocator& allocator = m_context.getDefaultAllocator();
914 m_image = de::MovePtr<Image>(new Image(
915 vk, device, allocator,
916 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
917 MemoryRequirement::Any));
919 // This buffer will be used to pass constants to the shader
921 const int numLayers = m_texture.numLayers();
922 const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
923 m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
924 vk, device, allocator,
925 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
926 MemoryRequirement::HostVisible));
929 const Allocation& alloc = m_constantsBuffer->getAllocation();
930 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
932 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
934 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
936 deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
937 *valuePtr = static_cast<deUint32>(layerNdx);
940 flushAlloc(vk, device, alloc);
944 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
946 const DeviceInterface& vk = m_context.getDeviceInterface();
947 const VkDevice device = m_context.getDevice();
949 const int numLayers = m_texture.numLayers();
950 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
951 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
952 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
955 m_descriptorPool = DescriptorPoolBuilder()
956 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
957 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
958 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
960 if (m_singleLayerBind)
962 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
964 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
965 m_allImageViews[layerNdx] = makeVkSharedPtr(makeImageView(
966 vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
967 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
970 else // bind all layers at once
972 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
973 m_allImageViews[0] = makeVkSharedPtr(makeImageView(
974 vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
975 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
978 return *m_descriptorSetLayout; // not passing the ownership
981 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
983 const DeviceInterface& vk = m_context.getDeviceInterface();
984 const VkDevice device = m_context.getDevice();
986 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
987 const VkImageView imageView = **m_allImageViews[layerNdx];
989 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
991 // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
992 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
993 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
995 DescriptorSetUpdateBuilder()
996 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
997 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
999 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1002 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1004 const DeviceInterface& vk = m_context.getDeviceInterface();
1006 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1007 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
1008 0u, VK_ACCESS_SHADER_WRITE_BIT,
1009 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1010 m_image->get(), fullImageSubresourceRange);
1012 const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
1013 const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
1014 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1015 m_constantsBuffer->get(), 0ull, constantsBufferSize);
1017 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier);
1020 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1022 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
1025 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1027 commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1030 //! Store test for buffers
1031 class BufferStoreTestInstance : public StoreTestInstance
1034 BufferStoreTestInstance (Context& context,
1035 const Texture& texture,
1036 const VkFormat format,
1037 const bool declareImageFormatInShader,
1038 const bool minalign,
1039 const bool storeConstantValue);
1042 VkDescriptorSetLayout prepareDescriptors (void);
1043 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1045 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1046 const VkPipelineLayout pipelineLayout,
1047 const int layerNdx);
1049 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1050 Move<VkDescriptorPool> m_descriptorPool;
1051 Move<VkDescriptorSet> m_descriptorSet;
1052 Move<VkBufferView> m_bufferView;
1055 BufferStoreTestInstance::BufferStoreTestInstance (Context& context,
1056 const Texture& texture,
1057 const VkFormat format,
1058 const bool declareImageFormatInShader,
1059 const bool minalign,
1060 const bool storeConstantValue)
1061 : StoreTestInstance(context, texture, format, declareImageFormatInShader, false, minalign, storeConstantValue)
1065 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
1067 const DeviceInterface& vk = m_context.getDeviceInterface();
1068 const VkDevice device = m_context.getDevice();
1070 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1071 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1074 m_descriptorPool = DescriptorPoolBuilder()
1075 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1076 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1078 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1079 m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_dstViewOffset, m_imageSizeBytes);
1081 return *m_descriptorSetLayout; // not passing the ownership
1084 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1086 DE_ASSERT(layerNdx == 0);
1089 const VkDevice device = m_context.getDevice();
1090 const DeviceInterface& vk = m_context.getDeviceInterface();
1092 DescriptorSetUpdateBuilder()
1093 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
1094 .update(vk, device);
1095 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1098 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1100 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes + m_dstViewOffset);
1103 class LoadStoreTest : public TestCase
1108 FLAG_SINGLE_LAYER_BIND = 1 << 0, //!< Run the shader multiple times, each time binding a different layer.
1109 FLAG_RESTRICT_IMAGES = 1 << 1, //!< If given, images in the shader will be qualified with "restrict".
1110 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 1 << 2, //!< Declare the format of the images in the shader code
1111 FLAG_MINALIGN = 1 << 3, //!< Use bufferview offset that matches the advertised minimum alignment
1112 FLAG_UNIFORM_TEXEL_BUFFER = 1 << 4, //!< Load from a uniform texel buffer rather than a storage texel buffer
1115 LoadStoreTest (tcu::TestContext& testCtx,
1116 const std::string& name,
1117 const std::string& description,
1118 const Texture& texture,
1119 const VkFormat format,
1120 const VkFormat imageFormat,
1121 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER,
1122 const deBool imageLoadStoreLodAMD = DE_FALSE);
1124 virtual void checkSupport (Context& context) const;
1125 void initPrograms (SourceCollections& programCollection) const;
1126 TestInstance* createInstance (Context& context) const;
1129 const Texture m_texture;
1130 const VkFormat m_format; //!< Format as accessed in the shader
1131 const VkFormat m_imageFormat; //!< Storage format
1132 const bool m_declareImageFormatInShader; //!< Whether the shader will specify the format layout qualifier of the images
1133 const bool m_singleLayerBind;
1134 const bool m_restrictImages;
1135 const bool m_minalign;
1136 bool m_bufferLoadUniform;
1137 const deBool m_imageLoadStoreLodAMD;
1140 LoadStoreTest::LoadStoreTest (tcu::TestContext& testCtx,
1141 const std::string& name,
1142 const std::string& description,
1143 const Texture& texture,
1144 const VkFormat format,
1145 const VkFormat imageFormat,
1146 const deUint32 flags,
1147 const deBool imageLoadStoreLodAMD)
1148 : TestCase (testCtx, name, description)
1149 , m_texture (texture)
1151 , m_imageFormat (imageFormat)
1152 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
1153 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
1154 , m_restrictImages ((flags & FLAG_RESTRICT_IMAGES) != 0)
1155 , m_minalign ((flags & FLAG_MINALIGN) != 0)
1156 , m_bufferLoadUniform ((flags & FLAG_UNIFORM_TEXEL_BUFFER) != 0)
1157 , m_imageLoadStoreLodAMD (imageLoadStoreLodAMD)
1159 if (m_singleLayerBind)
1160 DE_ASSERT(m_texture.numLayers() > 1);
1162 DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
1165 void LoadStoreTest::checkSupport (Context& context) const
1167 #ifndef CTS_USES_VULKANSC
1168 const VkFormatProperties3 formatProperties (context.getFormatProperties(m_format));
1169 const VkFormatProperties3 imageFormatProperties (context.getFormatProperties(m_imageFormat));
1171 if (m_imageLoadStoreLodAMD)
1172 context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1174 if (!m_bufferLoadUniform && !m_declareImageFormatInShader && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR))
1175 TCU_THROW(NotSupportedError, "Format not supported for unformatted loads via storage images");
1177 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1178 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1180 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1181 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1183 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1184 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1186 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1187 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1189 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageFormatProperties.optimalTilingFeatures))
1190 TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1192 if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1193 TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1195 if (formatHasThreeComponents(m_format))
1197 // When the source buffer is three-component, the destination buffer is single-component.
1198 VkFormat dstFormat = getSingleComponentFormat(m_format);
1199 const VkFormatProperties3 dstFormatProperties (context.getFormatProperties(dstFormat));
1201 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1202 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1205 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1206 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1208 if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1209 TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1211 const vk::VkFormatProperties formatProperties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1212 context.getPhysicalDevice(),
1214 const vk::VkFormatProperties imageFormatProperties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1215 context.getPhysicalDevice(),
1217 if (m_imageLoadStoreLodAMD)
1218 context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1220 if (!m_bufferLoadUniform && !m_declareImageFormatInShader)
1221 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT);
1223 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1224 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1226 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1227 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1229 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1230 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1232 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1233 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1235 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageFormatProperties.optimalTilingFeatures))
1236 TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1238 if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1239 TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1241 if (formatHasThreeComponents(m_format))
1243 // When the source buffer is three-component, the destination buffer is single-component.
1244 VkFormat dstFormat = getSingleComponentFormat(m_format);
1245 const vk::VkFormatProperties dstFormatProperties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1246 context.getPhysicalDevice(),
1249 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1250 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1253 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1254 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1256 if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1257 TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1258 #endif // CTS_USES_VULKANSC
1261 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
1263 const tcu::TextureFormat texFormat = mapVkFormat(m_format);
1264 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
1265 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
1266 const std::string formatQualifierStr = getShaderImageFormatQualifier(texFormat);
1267 const std::string uniformTypeStr = getFormatPrefix(texFormat) + "textureBuffer";
1268 const std::string imageTypeStr = getShaderImageType(texFormat, usedImageType);
1269 const std::string maybeRestrictStr = (m_restrictImages ? "restrict " : "");
1270 const std::string xMax = de::toString(m_texture.size().x() - 1);
1272 std::ostringstream src;
1273 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1275 if (!m_declareImageFormatInShader)
1277 src << "#extension GL_EXT_shader_image_load_formatted : require\n";
1280 if (m_imageLoadStoreLodAMD)
1282 src << "#extension GL_AMD_shader_image_load_store_lod : require\n";
1285 src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
1286 if (m_bufferLoadUniform)
1287 src << "layout (binding = 0) uniform " << uniformTypeStr << " u_image0;\n";
1288 else if (m_declareImageFormatInShader)
1289 src << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1291 src << "layout (binding = 0) " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1293 if (formatHasThreeComponents(m_format))
1294 src << "layout (binding = 1) " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1296 src << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1299 << "void main (void)\n"
1303 default: DE_ASSERT(0); // fallthrough
1305 if (m_bufferLoadUniform)
1307 // for three-component formats, the dst buffer is single-component and the shader
1308 // expands the store into 3 component-wise stores.
1309 std::string type = getFormatPrefix(texFormat) + "vec4";
1310 src << " int pos = int(gl_GlobalInvocationID.x);\n"
1311 " " << type << " t = texelFetch(u_image0, " + xMax + "-pos);\n";
1312 if (formatHasThreeComponents(m_format))
1314 src << " imageStore(u_image1, 3*pos+0, " << type << "(t.x));\n";
1315 src << " imageStore(u_image1, 3*pos+1, " << type << "(t.y));\n";
1316 src << " imageStore(u_image1, 3*pos+2, " << type << "(t.z));\n";
1319 src << " imageStore(u_image1, pos, t);\n";
1321 else if (m_imageLoadStoreLodAMD)
1324 " int pos = int(gl_GlobalInvocationID.x);\n";
1326 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1328 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1329 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, " + xMaxSize + "-pos, " + de::toString(levelNdx) + "));\n";
1335 " int pos = int(gl_GlobalInvocationID.x);\n"
1336 " imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n";
1340 if (m_imageLoadStoreLodAMD)
1342 src << " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
1344 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1346 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1347 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec2(" + xMaxSize + "-pos.x, pos.y), " + de::toString(levelNdx) + "));\n";
1354 " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
1355 " imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n";
1359 if (m_imageLoadStoreLodAMD)
1361 src << " ivec3 pos = ivec3(gl_GlobalInvocationID);\n";
1363 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1365 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1366 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec3(" + xMaxSize + "-pos.x, pos.y, pos.z), " + de::toString(levelNdx) + "));\n";
1372 " ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
1373 " imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n";
1379 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1382 //! Load/store test base implementation
1383 class LoadStoreTestInstance : public BaseTestInstance
1386 LoadStoreTestInstance (Context& context,
1387 const Texture& texture,
1388 const VkFormat format,
1389 const VkFormat imageFormat,
1390 const bool declareImageFormatInShader,
1391 const bool singleLayerBind,
1392 const bool minalign,
1393 const bool bufferLoadUniform);
1396 virtual Buffer* getResultBuffer (void) const = 0; //!< Get the buffer that contains the result image
1398 tcu::TestStatus verifyResult (void);
1400 // Add empty implementations for functions that might be not needed
1401 void commandBeforeCompute (const VkCommandBuffer) {}
1402 void commandBetweenShaderInvocations (const VkCommandBuffer) {}
1403 void commandAfterCompute (const VkCommandBuffer) {}
1405 de::MovePtr<Buffer> m_imageBuffer; //!< Source data and helper buffer
1406 const VkDeviceSize m_imageSizeBytes;
1407 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
1408 tcu::TextureLevel m_referenceImage; //!< Used as input data and later to verify result image
1410 bool m_bufferLoadUniform;
1411 VkDescriptorType m_bufferLoadDescriptorType;
1412 VkBufferUsageFlagBits m_bufferLoadUsageBit;
1415 LoadStoreTestInstance::LoadStoreTestInstance (Context& context,
1416 const Texture& texture,
1417 const VkFormat format,
1418 const VkFormat imageFormat,
1419 const bool declareImageFormatInShader,
1420 const bool singleLayerBind,
1421 const bool minalign,
1422 const bool bufferLoadUniform)
1423 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1424 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format))
1425 , m_imageFormat (imageFormat)
1426 , m_referenceImage (generateReferenceImage(texture.size(), imageFormat, format))
1427 , m_bufferLoadUniform (bufferLoadUniform)
1429 const DeviceInterface& vk = m_context.getDeviceInterface();
1430 const VkDevice device = m_context.getDevice();
1431 Allocator& allocator = m_context.getDefaultAllocator();
1433 m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1434 m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1436 // A helper buffer with enough space to hold the whole image.
1438 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
1439 vk, device, allocator,
1440 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1441 MemoryRequirement::HostVisible));
1443 // Copy reference data to buffer for subsequent upload to image.
1445 const Allocation& alloc = m_imageBuffer->getAllocation();
1446 deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset, m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
1447 flushAlloc(vk, device, alloc);
1450 tcu::TestStatus LoadStoreTestInstance::verifyResult (void)
1452 const DeviceInterface& vk = m_context.getDeviceInterface();
1453 const VkDevice device = m_context.getDevice();
1455 // Apply the same transformation as done in the shader
1456 const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
1457 flipHorizontally(reference);
1459 const Allocation& alloc = getResultBuffer()->getAllocation();
1460 invalidateAlloc(vk, device, alloc);
1461 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), (const char *)alloc.getHostPtr() + m_dstViewOffset);
1463 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
1464 return tcu::TestStatus::pass("Passed");
1466 return tcu::TestStatus::fail("Image comparison failed");
1469 //! Load/store test for images
1470 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
1473 ImageLoadStoreTestInstance (Context& context,
1474 const Texture& texture,
1475 const VkFormat format,
1476 const VkFormat imageFormat,
1477 const bool declareImageFormatInShader,
1478 const bool singleLayerBind,
1479 const bool minalign,
1480 const bool bufferLoadUniform);
1483 VkDescriptorSetLayout prepareDescriptors (void);
1484 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
1485 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
1486 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1488 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1489 const VkPipelineLayout pipelineLayout,
1490 const int layerNdx);
1492 Buffer* getResultBuffer (void) const { return m_imageBuffer.get(); }
1494 de::MovePtr<Image> m_imageSrc;
1495 de::MovePtr<Image> m_imageDst;
1496 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1497 Move<VkDescriptorPool> m_descriptorPool;
1498 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1499 std::vector<SharedVkImageView> m_allSrcImageViews;
1500 std::vector<SharedVkImageView> m_allDstImageViews;
1503 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context& context,
1504 const Texture& texture,
1505 const VkFormat format,
1506 const VkFormat imageFormat,
1507 const bool declareImageFormatInShader,
1508 const bool singleLayerBind,
1509 const bool minalign,
1510 const bool bufferLoadUniform)
1511 : LoadStoreTestInstance (context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1512 , m_allDescriptorSets (texture.numLayers())
1513 , m_allSrcImageViews (texture.numLayers())
1514 , m_allDstImageViews (texture.numLayers())
1516 const DeviceInterface& vk = m_context.getDeviceInterface();
1517 const VkDevice device = m_context.getDevice();
1518 Allocator& allocator = m_context.getDefaultAllocator();
1519 const VkImageCreateFlags imageFlags = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1521 m_imageSrc = de::MovePtr<Image>(new Image(
1522 vk, device, allocator,
1523 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags),
1524 MemoryRequirement::Any));
1526 m_imageDst = de::MovePtr<Image>(new Image(
1527 vk, device, allocator,
1528 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags),
1529 MemoryRequirement::Any));
1532 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1534 const VkDevice device = m_context.getDevice();
1535 const DeviceInterface& vk = m_context.getDeviceInterface();
1537 const int numLayers = m_texture.numLayers();
1538 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1539 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1540 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1543 m_descriptorPool = DescriptorPoolBuilder()
1544 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1545 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1546 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1548 if (m_singleLayerBind)
1550 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1552 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1553 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1555 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1556 m_allSrcImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1557 m_allDstImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1560 else // bind all layers at once
1562 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1563 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1565 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1566 m_allSrcImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1567 m_allDstImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1570 return *m_descriptorSetLayout; // not passing the ownership
1573 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1575 const VkDevice device = m_context.getDevice();
1576 const DeviceInterface& vk = m_context.getDeviceInterface();
1578 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1579 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
1580 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
1582 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1583 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1585 DescriptorSetUpdateBuilder()
1586 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1587 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1588 .update(vk, device);
1589 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1592 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1594 const DeviceInterface& vk = m_context.getDeviceInterface();
1596 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1598 const VkImageMemoryBarrier preCopyImageBarriers[] =
1600 makeImageMemoryBarrier(
1601 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1602 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1603 m_imageSrc->get(), fullImageSubresourceRange),
1604 makeImageMemoryBarrier(
1605 0u, VK_ACCESS_SHADER_WRITE_BIT,
1606 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1607 m_imageDst->get(), fullImageSubresourceRange)
1610 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1611 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1612 m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1614 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1615 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1618 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1619 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1620 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1621 m_imageSrc->get(), fullImageSubresourceRange);
1623 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1625 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
1626 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy);
1630 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1632 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1635 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1637 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1640 //! Load/store Lod AMD test for images
1641 class ImageLoadStoreLodAMDTestInstance : public BaseTestInstance
1644 ImageLoadStoreLodAMDTestInstance (Context& context,
1645 const Texture& texture,
1646 const VkFormat format,
1647 const VkFormat imageFormat,
1648 const bool declareImageFormatInShader,
1649 const bool singleLayerBind,
1650 const bool minalign,
1651 const bool bufferLoadUniform);
1654 VkDescriptorSetLayout prepareDescriptors (void);
1655 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
1656 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
1657 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1659 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1660 const VkPipelineLayout pipelineLayout,
1661 const int layerNdx);
1663 Buffer* getResultBuffer (void) const { return m_imageBuffer.get(); }
1664 tcu::TestStatus verifyResult (void);
1666 de::MovePtr<Buffer> m_imageBuffer; //!< Source data and helper buffer
1667 const VkDeviceSize m_imageSizeBytes;
1668 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
1669 std::vector<tcu::TextureLevel> m_referenceImages; //!< Used as input data and later to verify result image
1671 bool m_bufferLoadUniform;
1672 VkDescriptorType m_bufferLoadDescriptorType;
1673 VkBufferUsageFlagBits m_bufferLoadUsageBit;
1675 de::MovePtr<Image> m_imageSrc;
1676 de::MovePtr<Image> m_imageDst;
1677 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1678 Move<VkDescriptorPool> m_descriptorPool;
1679 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1680 std::vector<SharedVkImageView> m_allSrcImageViews;
1681 std::vector<SharedVkImageView> m_allDstImageViews;
1685 ImageLoadStoreLodAMDTestInstance::ImageLoadStoreLodAMDTestInstance (Context& context,
1686 const Texture& texture,
1687 const VkFormat format,
1688 const VkFormat imageFormat,
1689 const bool declareImageFormatInShader,
1690 const bool singleLayerBind,
1691 const bool minalign,
1692 const bool bufferLoadUniform)
1693 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1694 , m_imageSizeBytes (getMipmapImageTotalSizeBytes(texture, format))
1695 , m_imageFormat (imageFormat)
1696 , m_bufferLoadUniform (bufferLoadUniform)
1697 , m_allDescriptorSets (texture.numLayers())
1698 , m_allSrcImageViews (texture.numLayers())
1699 , m_allDstImageViews (texture.numLayers())
1701 const DeviceInterface& vk = m_context.getDeviceInterface();
1702 const VkDevice device = m_context.getDevice();
1703 Allocator& allocator = m_context.getDefaultAllocator();
1704 const VkImageCreateFlags imageFlags = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1706 const VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(m_texture.numSamples()); // integer and bit mask are aligned, so we can cast like this
1708 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1710 tcu::TextureLevel referenceImage = generateReferenceImage(texture.size(levelNdx), imageFormat, format);
1711 m_referenceImages.push_back(referenceImage);
1714 m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1715 m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1717 // A helper buffer with enough space to hold the whole image.
1718 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
1719 vk, device, allocator,
1720 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1721 MemoryRequirement::HostVisible));
1723 // Copy reference data to buffer for subsequent upload to image.
1725 const Allocation& alloc = m_imageBuffer->getAllocation();
1726 VkDeviceSize bufferOffset = 0u;
1727 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1729 deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset + bufferOffset, m_referenceImages[levelNdx].getAccess().getDataPtr(), static_cast<size_t>(getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx)));
1730 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1732 flushAlloc(vk, device, alloc);
1736 const VkImageCreateInfo imageParamsSrc =
1738 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1739 DE_NULL, // const void* pNext;
1740 (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags, // VkImageCreateFlags flags;
1741 mapImageType(m_texture.type()), // VkImageType imageType;
1742 m_imageFormat, // VkFormat format;
1743 makeExtent3D(m_texture.layerSize()), // VkExtent3D extent;
1744 (deUint32)m_texture.numMipmapLevels(), // deUint32 mipLevels;
1745 (deUint32)m_texture.numLayers(), // deUint32 arrayLayers;
1746 samples, // VkSampleCountFlagBits samples;
1747 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1748 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
1749 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1750 0u, // deUint32 queueFamilyIndexCount;
1751 DE_NULL, // const deUint32* pQueueFamilyIndices;
1752 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1755 m_imageSrc = de::MovePtr<Image>(new Image(
1756 vk, device, allocator,
1758 MemoryRequirement::Any));
1762 const VkImageCreateInfo imageParamsDst =
1764 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1765 DE_NULL, // const void* pNext;
1766 (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags, // VkImageCreateFlags flags;
1767 mapImageType(m_texture.type()), // VkImageType imageType;
1768 m_imageFormat, // VkFormat format;
1769 makeExtent3D(m_texture.layerSize()), // VkExtent3D extent;
1770 (deUint32)m_texture.numMipmapLevels(), // deUint32 mipLevels;
1771 (deUint32)m_texture.numLayers(), // deUint32 arrayLayers;
1772 samples, // VkSampleCountFlagBits samples;
1773 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1774 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1775 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1776 0u, // deUint32 queueFamilyIndexCount;
1777 DE_NULL, // const deUint32* pQueueFamilyIndices;
1778 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1781 m_imageDst = de::MovePtr<Image>(new Image(
1782 vk, device, allocator,
1784 MemoryRequirement::Any));
1788 tcu::TestStatus ImageLoadStoreLodAMDTestInstance::verifyResult (void)
1790 const DeviceInterface& vk = m_context.getDeviceInterface();
1791 const VkDevice device = m_context.getDevice();
1793 const Allocation& alloc = getResultBuffer()->getAllocation();
1794 invalidateAlloc(vk, device, alloc);
1796 VkDeviceSize bufferOffset = 0;
1797 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1799 // Apply the same transformation as done in the shader
1800 const tcu::PixelBufferAccess reference = m_referenceImages[levelNdx].getAccess();
1801 flipHorizontally(reference);
1803 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(levelNdx), (const char *)alloc.getHostPtr() + m_dstViewOffset + bufferOffset);
1805 if (!comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result, levelNdx))
1807 std::ostringstream errorMessage;
1808 errorMessage << "Image Level " << levelNdx << " comparison failed";
1809 return tcu::TestStatus::fail(errorMessage.str());
1811 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1814 return tcu::TestStatus::pass("Passed");
1817 VkDescriptorSetLayout ImageLoadStoreLodAMDTestInstance::prepareDescriptors (void)
1819 const VkDevice device = m_context.getDevice();
1820 const DeviceInterface& vk = m_context.getDeviceInterface();
1822 const int numLayers = m_texture.numLayers();
1823 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1824 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1825 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1828 m_descriptorPool = DescriptorPoolBuilder()
1829 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1830 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1831 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1833 if (m_singleLayerBind)
1835 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1837 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1838 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), layerNdx, 1u);
1840 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1841 m_allSrcImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1842 m_allDstImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1845 else // bind all layers at once
1847 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1848 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, numLayers);
1850 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1851 m_allSrcImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1852 m_allDstImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1855 return *m_descriptorSetLayout; // not passing the ownership
1858 void ImageLoadStoreLodAMDTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1860 const VkDevice device = m_context.getDevice();
1861 const DeviceInterface& vk = m_context.getDeviceInterface();
1863 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1864 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
1865 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
1867 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1868 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1870 DescriptorSetUpdateBuilder()
1871 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1872 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1873 .update(vk, device);
1874 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1877 void ImageLoadStoreLodAMDTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1879 const DeviceInterface& vk = m_context.getDeviceInterface();
1880 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, m_texture.numLayers());
1882 const VkImageMemoryBarrier preCopyImageBarriers[] =
1884 makeImageMemoryBarrier(
1885 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1886 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1887 m_imageSrc->get(), fullImageSubresourceRange),
1888 makeImageMemoryBarrier(
1889 0u, VK_ACCESS_SHADER_WRITE_BIT,
1890 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1891 m_imageDst->get(), fullImageSubresourceRange)
1894 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1895 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1896 m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1898 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1899 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1902 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1903 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1904 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1905 m_imageSrc->get(), fullImageSubresourceRange);
1907 std::vector<VkBufferImageCopy> copyRegions;
1908 VkDeviceSize bufferOffset = 0u;
1909 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1911 const VkBufferImageCopy copyParams =
1913 bufferOffset, // VkDeviceSize bufferOffset;
1914 0u, // deUint32 bufferRowLength;
1915 0u, // deUint32 bufferImageHeight;
1916 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, m_texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
1917 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1918 makeExtent3D(m_texture.layerSize(levelNdx)), // VkExtent3D imageExtent;
1920 copyRegions.push_back(copyParams);
1921 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1924 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32) copyRegions.size(), copyRegions.data());
1925 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy);
1929 void ImageLoadStoreLodAMDTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1931 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1934 void ImageLoadStoreLodAMDTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1936 commandCopyMipmapImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageFormat, m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1939 //! Load/store test for buffers
1940 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
1943 BufferLoadStoreTestInstance (Context& context,
1944 const Texture& texture,
1945 const VkFormat format,
1946 const VkFormat imageFormat,
1947 const bool declareImageFormatInShader,
1948 const bool minalign,
1949 const bool bufferLoadUniform);
1952 VkDescriptorSetLayout prepareDescriptors (void);
1953 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1955 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1956 const VkPipelineLayout pipelineLayout,
1957 const int layerNdx);
1959 Buffer* getResultBuffer (void) const { return m_imageBufferDst.get(); }
1961 de::MovePtr<Buffer> m_imageBufferDst;
1962 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1963 Move<VkDescriptorPool> m_descriptorPool;
1964 Move<VkDescriptorSet> m_descriptorSet;
1965 Move<VkBufferView> m_bufferViewSrc;
1966 Move<VkBufferView> m_bufferViewDst;
1969 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context& context,
1970 const Texture& texture,
1971 const VkFormat format,
1972 const VkFormat imageFormat,
1973 const bool declareImageFormatInShader,
1974 const bool minalign,
1975 const bool bufferLoadUniform)
1976 : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false, minalign, bufferLoadUniform)
1978 const DeviceInterface& vk = m_context.getDeviceInterface();
1979 const VkDevice device = m_context.getDevice();
1980 Allocator& allocator = m_context.getDefaultAllocator();
1982 // Create a destination buffer.
1984 m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
1985 vk, device, allocator,
1986 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
1987 MemoryRequirement::HostVisible));
1990 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
1992 const DeviceInterface& vk = m_context.getDeviceInterface();
1993 const VkDevice device = m_context.getDevice();
1995 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1996 .addSingleBinding(m_bufferLoadDescriptorType, VK_SHADER_STAGE_COMPUTE_BIT)
1997 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2000 m_descriptorPool = DescriptorPoolBuilder()
2001 .addType(m_bufferLoadDescriptorType)
2002 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
2003 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2005 VkFormat dstFormat = formatHasThreeComponents(m_format) ? getSingleComponentFormat(m_format) : m_format;
2007 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2008 m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_srcViewOffset, m_imageSizeBytes);
2009 m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), dstFormat, m_dstViewOffset, m_imageSizeBytes);
2011 return *m_descriptorSetLayout; // not passing the ownership
2014 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
2016 DE_ASSERT(layerNdx == 0);
2019 const VkDevice device = m_context.getDevice();
2020 const DeviceInterface& vk = m_context.getDeviceInterface();
2022 DescriptorSetUpdateBuilder()
2023 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), m_bufferLoadDescriptorType, &m_bufferViewSrc.get())
2024 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
2025 .update(vk, device);
2026 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
2029 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
2031 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes + m_dstViewOffset);
2034 TestInstance* StoreTest::createInstance (Context& context) const
2036 if (m_texture.type() == IMAGE_TYPE_BUFFER)
2037 return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_minalign, m_storeConstantValue);
2039 return new ImageStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_storeConstantValue);
2042 TestInstance* LoadStoreTest::createInstance (Context& context) const
2044 if (m_imageLoadStoreLodAMD)
2045 return new ImageLoadStoreLodAMDTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
2047 if (m_texture.type() == IMAGE_TYPE_BUFFER)
2048 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_minalign, m_bufferLoadUniform);
2050 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
2053 class ImageExtendOperandTestInstance : public BaseTestInstance
2056 ImageExtendOperandTestInstance (Context& context,
2057 const Texture& texture,
2058 const VkFormat readFormat,
2059 const VkFormat writeFormat,
2060 bool relaxedPrecision);
2062 virtual ~ImageExtendOperandTestInstance (void) {}
2066 VkDescriptorSetLayout prepareDescriptors (void);
2067 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
2068 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
2069 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
2071 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
2072 const VkPipelineLayout pipelineLayout,
2073 const int layerNdx);
2075 tcu::TestStatus verifyResult (void);
2080 tcu::TextureLevel m_inputImageData;
2082 de::MovePtr<Image> m_imageSrc; // source image
2083 SharedVkImageView m_imageSrcView;
2084 VkDeviceSize m_imageSrcSize;
2086 de::MovePtr<Image> m_imageDst; // dest image
2087 SharedVkImageView m_imageDstView;
2088 VkFormat m_imageDstFormat;
2089 VkDeviceSize m_imageDstSize;
2091 de::MovePtr<Buffer> m_buffer; // result buffer
2093 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2094 Move<VkDescriptorPool> m_descriptorPool;
2095 SharedVkDescriptorSet m_descriptorSet;
2097 bool m_relaxedPrecision;
2100 ImageExtendOperandTestInstance::ImageExtendOperandTestInstance (Context& context,
2101 const Texture& texture,
2102 const VkFormat readFormat,
2103 const VkFormat writeFormat,
2104 bool relaxedPrecision)
2105 : BaseTestInstance (context, texture, readFormat, true, true, false, false)
2106 , m_imageDstFormat (writeFormat)
2107 , m_relaxedPrecision (relaxedPrecision)
2109 const DeviceInterface& vk = m_context.getDeviceInterface();
2110 const VkDevice device = m_context.getDevice();
2111 Allocator& allocator = m_context.getDefaultAllocator();
2112 const deInt32 width = texture.size().x();
2113 const deInt32 height = texture.size().y();
2114 const tcu::TextureFormat textureFormat = mapVkFormat(m_format);
2116 // Generate reference image
2117 m_isSigned = (getTextureChannelClass(textureFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2118 m_inputImageData.setStorage(textureFormat, width, height, 1);
2120 const tcu::PixelBufferAccess access = m_inputImageData.getAccess();
2121 const int valueStart = (m_isSigned ? (-width / 2) : 0);
2123 for (int x = 0; x < width; ++x)
2124 for (int y = 0; y < height; ++y)
2126 const tcu::IVec4 color(valueStart + x, valueStart + y, valueStart, valueStart);
2127 access.setPixel(color, x, y);
2130 // Create source image
2131 m_imageSrc = de::MovePtr<Image>(new Image(
2132 vk, device, allocator,
2133 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0u),
2134 MemoryRequirement::Any));
2136 // Create destination image
2137 m_imageDst = de::MovePtr<Image>(new Image(
2138 vk, device, allocator,
2139 makeImageCreateInfo(m_texture, m_imageDstFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
2140 MemoryRequirement::Any));
2142 // Compute image and buffer sizes
2143 m_imageSrcSize = width * height * tcu::getPixelSize(textureFormat);
2144 m_imageDstSize = width * height * tcu::getPixelSize(mapVkFormat(m_imageDstFormat));
2145 VkDeviceSize bufferSizeBytes = de::max(m_imageSrcSize, m_imageDstSize);
2147 // Create helper buffer able to store input data and image write result
2148 m_buffer = de::MovePtr<Buffer>(new Buffer(
2149 vk, device, allocator,
2150 makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
2151 MemoryRequirement::HostVisible));
2153 const Allocation& alloc = m_buffer->getAllocation();
2154 deMemcpy(alloc.getHostPtr(), m_inputImageData.getAccess().getDataPtr(), static_cast<size_t>(m_imageSrcSize));
2155 flushAlloc(vk, device, alloc);
2158 VkDescriptorSetLayout ImageExtendOperandTestInstance::prepareDescriptors (void)
2160 const DeviceInterface& vk = m_context.getDeviceInterface();
2161 const VkDevice device = m_context.getDevice();
2163 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2164 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2165 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2168 m_descriptorPool = DescriptorPoolBuilder()
2169 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2170 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2171 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
2173 const VkImageViewType viewType = mapImageViewType(m_texture.type());
2174 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2176 m_descriptorSet = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
2177 m_imageSrcView = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
2178 m_imageDstView = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_imageDstFormat, subresourceRange));
2180 return *m_descriptorSetLayout; // not passing the ownership
2183 void ImageExtendOperandTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
2187 const DeviceInterface& vk = m_context.getDeviceInterface();
2188 const VkDevice device = m_context.getDevice();
2189 const VkDescriptorSet descriptorSet = **m_descriptorSet;
2191 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageSrcView, VK_IMAGE_LAYOUT_GENERAL);
2192 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageDstView, VK_IMAGE_LAYOUT_GENERAL);
2194 typedef DescriptorSetUpdateBuilder::Location DSUBL;
2195 DescriptorSetUpdateBuilder()
2196 .writeSingle(descriptorSet, DSUBL::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
2197 .writeSingle(descriptorSet, DSUBL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
2198 .update(vk, device);
2199 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
2202 void ImageExtendOperandTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
2204 const DeviceInterface& vk = m_context.getDeviceInterface();
2206 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
2208 const VkImageMemoryBarrier preCopyImageBarriers[] =
2210 makeImageMemoryBarrier(
2211 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
2212 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2213 m_imageSrc->get(), fullImageSubresourceRange),
2214 makeImageMemoryBarrier(
2215 0u, VK_ACCESS_SHADER_WRITE_BIT,
2216 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
2217 m_imageDst->get(), fullImageSubresourceRange)
2220 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
2221 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2222 m_buffer->get(), 0ull, m_imageSrcSize);
2224 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
2225 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
2228 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
2229 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
2230 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
2231 m_imageSrc->get(), fullImageSubresourceRange);
2233 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
2235 vk.cmdCopyBufferToImage(cmdBuffer, m_buffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
2236 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy);
2240 void ImageExtendOperandTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
2242 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
2245 void ImageExtendOperandTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
2247 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_buffer->get(), m_imageDstSize, m_texture);
2250 // Clears the high bits of every pixel in the pixel buffer, leaving only the lowest 16 bits of each component.
2251 void clearHighBits (const tcu::PixelBufferAccess& pixels, int width, int height)
2253 for (int y = 0; y < height; ++y)
2254 for (int x = 0; x < width; ++x)
2256 auto color = pixels.getPixelUint(x, y);
2257 for (int c = 0; c < decltype(color)::SIZE; ++c)
2258 color[c] &= 0xFFFFull;
2259 pixels.setPixel(color, x, y);
2263 tcu::TestStatus ImageExtendOperandTestInstance::verifyResult (void)
2265 const DeviceInterface& vk = m_context.getDeviceInterface();
2266 const VkDevice device = m_context.getDevice();
2267 const tcu::IVec3 imageSize = m_texture.size();
2268 const tcu::PixelBufferAccess inputAccess = m_inputImageData.getAccess();
2269 const deInt32 width = inputAccess.getWidth();
2270 const deInt32 height = inputAccess.getHeight();
2271 tcu::TextureLevel refImage (mapVkFormat(m_imageDstFormat), width, height);
2272 tcu::PixelBufferAccess refAccess = refImage.getAccess();
2274 for (int x = 0; x < width; ++x)
2275 for (int y = 0; y < height; ++y)
2277 tcu::IVec4 color = inputAccess.getPixelInt(x, y);
2278 refAccess.setPixel(color, x, y);
2281 const Allocation& alloc = m_buffer->getAllocation();
2282 invalidateAlloc(vk, device, alloc);
2283 const tcu::PixelBufferAccess result(mapVkFormat(m_imageDstFormat), imageSize, alloc.getHostPtr());
2285 if (m_relaxedPrecision)
2287 // Preserve the lowest 16 bits of the reference and result pixels only.
2288 clearHighBits(refAccess, width, height);
2289 clearHighBits(result, width, height);
2292 if (tcu::intThresholdCompare (m_context.getTestContext().getLog(), "Comparison", "Comparison", refAccess, result, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT, true/*use64Bits*/))
2293 return tcu::TestStatus::pass("Passed");
2295 return tcu::TestStatus::fail("Image comparison failed");
2298 enum class ExtendTestType
2305 enum class ExtendOperand
2311 class ImageExtendOperandTest : public TestCase
2314 ImageExtendOperandTest (tcu::TestContext& testCtx,
2315 const std::string& name,
2316 const Texture texture,
2317 const VkFormat readFormat,
2318 const VkFormat writeFormat,
2319 const bool signedInt,
2320 const bool relaxedPrecision,
2321 ExtendTestType extendTestType);
2323 void checkSupport (Context& context) const;
2324 void initPrograms (SourceCollections& programCollection) const;
2325 TestInstance* createInstance (Context& context) const;
2328 bool isWriteTest () const { return (m_extendTestType == ExtendTestType::WRITE) ||
2329 (m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL); }
2331 const Texture m_texture;
2332 VkFormat m_readFormat;
2333 VkFormat m_writeFormat;
2334 bool m_operandForce; // Use an operand that doesn't match SampledType?
2335 bool m_relaxedPrecision;
2336 ExtendTestType m_extendTestType;
2339 ImageExtendOperandTest::ImageExtendOperandTest (tcu::TestContext& testCtx,
2340 const std::string& name,
2341 const Texture texture,
2342 const VkFormat readFormat,
2343 const VkFormat writeFormat,
2344 const bool operandForce,
2345 const bool relaxedPrecision,
2346 ExtendTestType extendTestType)
2347 : TestCase (testCtx, name, "")
2348 , m_texture (texture)
2349 , m_readFormat (readFormat)
2350 , m_writeFormat (writeFormat)
2351 , m_operandForce (operandForce)
2352 , m_relaxedPrecision (relaxedPrecision)
2353 , m_extendTestType (extendTestType)
2357 void checkFormatProperties (Context& context, VkFormat format)
2359 #ifndef CTS_USES_VULKANSC
2360 const VkFormatProperties3 formatProperties (context.getFormatProperties(format));
2362 if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2363 TCU_THROW(NotSupportedError, "Format not supported for storage images");
2365 const VkFormatProperties formatProperties(getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), format));
2367 if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2368 TCU_THROW(NotSupportedError, "Format not supported for storage images");
2369 #endif // CTS_USES_VULKANSC
2372 void check64BitSupportIfNeeded (Context& context, VkFormat readFormat, VkFormat writeFormat)
2374 if (is64BitIntegerFormat(readFormat) || is64BitIntegerFormat(writeFormat))
2376 const auto& features = context.getDeviceFeatures();
2377 if (!features.shaderInt64)
2378 TCU_THROW(NotSupportedError, "64-bit integers not supported in shaders");
2382 void ImageExtendOperandTest::checkSupport (Context& context) const
2384 if (!context.requireDeviceFunctionality("VK_KHR_spirv_1_4"))
2385 TCU_THROW(NotSupportedError, "VK_KHR_spirv_1_4 not supported");
2387 #ifndef CTS_USES_VULKANSC
2388 if ((m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL) &&
2389 (context.getUsedApiVersion() < VK_API_VERSION_1_3))
2390 TCU_THROW(NotSupportedError, "Vulkan 1.3 or higher is required for this test to run");
2391 #endif // CTS_USES_VULKANSC
2393 check64BitSupportIfNeeded(context, m_readFormat, m_writeFormat);
2395 checkFormatProperties(context, m_readFormat);
2396 checkFormatProperties(context, m_writeFormat);
2399 void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection) const
2401 tcu::StringTemplate shaderTemplate(
2402 "OpCapability Shader\n"
2403 "OpCapability StorageImageExtendedFormats\n"
2408 "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
2409 "OpMemoryModel Logical GLSL450\n"
2410 "OpEntryPoint GLCompute %main \"main\" %id %src_image_ptr %dst_image_ptr\n"
2411 "OpExecutionMode %main LocalSize 1 1 1\n"
2414 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2416 "OpDecorate %src_image_ptr DescriptorSet 0\n"
2417 "OpDecorate %src_image_ptr Binding 0\n"
2418 "OpDecorate %src_image_ptr NonWritable\n"
2420 "${relaxed_precision}"
2422 "OpDecorate %dst_image_ptr DescriptorSet 0\n"
2423 "OpDecorate %dst_image_ptr Binding 1\n"
2424 "OpDecorate %dst_image_ptr NonReadable\n"
2427 "%type_void = OpTypeVoid\n"
2428 "%type_i32 = OpTypeInt 32 1\n"
2429 "%type_u32 = OpTypeInt 32 0\n"
2430 "%type_vec2_i32 = OpTypeVector %type_i32 2\n"
2431 "%type_vec2_u32 = OpTypeVector %type_u32 2\n"
2432 "%type_vec3_i32 = OpTypeVector %type_i32 3\n"
2433 "%type_vec3_u32 = OpTypeVector %type_u32 3\n"
2434 "%type_vec4_i32 = OpTypeVector %type_i32 4\n"
2435 "%type_vec4_u32 = OpTypeVector %type_u32 4\n"
2438 "%type_fun_void = OpTypeFunction %type_void\n"
2442 "%type_ptr_in_vec3_u32 = OpTypePointer Input %type_vec3_u32\n"
2443 "%type_ptr_in_u32 = OpTypePointer Input %type_u32\n"
2448 "%id = OpVariable %type_ptr_in_vec3_u32 Input\n"
2450 "${image_variables}"
2453 "%main = OpFunction %type_void None %type_fun_void\n"
2454 "%label = OpLabel\n"
2458 "%idvec = OpLoad %type_vec3_u32 %id\n"
2459 "%id_xy = OpVectorShuffle %type_vec2_u32 %idvec %idvec 0 1\n"
2460 "%coord = OpBitcast %type_vec2_i32 %id_xy\n"
2461 "%value = OpImageRead ${sampled_type_vec4} %src_image %coord ${read_extend_operand}\n"
2462 " OpImageWrite %dst_image %coord %value ${write_extend_operand}\n"
2464 " OpFunctionEnd\n");
2466 const auto testedFormat = mapVkFormat(isWriteTest() ? m_writeFormat : m_readFormat);
2467 const bool isSigned = (getTextureChannelClass(testedFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2469 const auto isRead64 = is64BitIntegerFormat(m_readFormat);
2470 const auto isWrite64 = is64BitIntegerFormat(m_writeFormat);
2471 DE_ASSERT(isRead64 == isWrite64);
2473 const bool using64Bits = (isRead64 || isWrite64);
2475 // Additional capabilities when needed.
2476 std::string capability;
2477 std::string extension;
2478 std::string extraTypes;
2482 extension += "OpExtension \"SPV_EXT_shader_image_int64\"\n";
2484 "OpCapability Int64\n"
2485 "OpCapability Int64ImageEXT\n"
2488 "%type_i64 = OpTypeInt 64 1\n"
2489 "%type_u64 = OpTypeInt 64 0\n"
2490 "%type_vec3_i64 = OpTypeVector %type_i64 3\n"
2491 "%type_vec3_u64 = OpTypeVector %type_u64 3\n"
2492 "%type_vec4_i64 = OpTypeVector %type_i64 4\n"
2493 "%type_vec4_u64 = OpTypeVector %type_u64 4\n"
2497 std::string relaxed = "";
2498 if (m_relaxedPrecision)
2499 relaxed += "OpDecorate %src_image_ptr RelaxedPrecision\n";
2501 // Sampled type depends on the format sign and mismatch force flag.
2502 const bool signedSampleType = ((isSigned && !m_operandForce) || (!isSigned && m_operandForce));
2503 const std::string bits = (using64Bits ? "64" : "32");
2504 const std::string sampledTypePostfix = (signedSampleType ? "i" : "u") + bits;
2505 const std::string extendOperandStr = (isSigned ? "SignExtend" : "ZeroExtend");
2507 std::map<std::string, std::string> specializations
2509 { "image_type_id", "%type_image" },
2510 { "image_uni_ptr_type_id", "%type_ptr_uniform_const_image" },
2511 { "image_var_id", "%src_image_ptr" },
2512 { "image_id", "%src_image" },
2513 { "capability", capability },
2514 { "extension", extension },
2515 { "extra_types", extraTypes },
2516 { "relaxed_precision", relaxed },
2517 { "image_format", getSpirvFormat(m_readFormat) },
2518 { "sampled_type", (std::string("%type_") + sampledTypePostfix) },
2519 { "sampled_type_vec4", (std::string("%type_vec4_") + sampledTypePostfix) },
2520 { "read_extend_operand", (!isWriteTest() ? extendOperandStr : "") },
2521 { "write_extend_operand", (isWriteTest() ? extendOperandStr : "") },
2524 SpirvVersion spirvVersion = SPIRV_VERSION_1_4;
2525 bool allowSpirv14 = true;
2526 if (m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL)
2528 spirvVersion = SPIRV_VERSION_1_6;
2529 allowSpirv14 = false;
2530 specializations["write_extend_operand"] = "Nontemporal";
2533 // Addidtional parametrization is needed for a case when source and destination textures have same format
2534 tcu::StringTemplate imageTypeTemplate(
2535 "${image_type_id} = OpTypeImage ${sampled_type} 2D 0 0 0 2 ${image_format}\n");
2536 tcu::StringTemplate imageUniformTypeTemplate(
2537 "${image_uni_ptr_type_id} = OpTypePointer UniformConstant ${image_type_id}\n");
2538 tcu::StringTemplate imageVariablesTemplate(
2539 "${image_var_id} = OpVariable ${image_uni_ptr_type_id} UniformConstant\n");
2540 tcu::StringTemplate imageLoadTemplate(
2541 "${image_id} = OpLoad ${image_type_id} ${image_var_id}\n");
2543 std::string imageTypes;
2544 std::string imageUniformTypes;
2545 std::string imageVariables;
2546 std::string imageLoad;
2548 // If input image format is the same as output there is less spir-v definitions
2549 if (m_readFormat == m_writeFormat)
2551 imageTypes = imageTypeTemplate.specialize(specializations);
2552 imageUniformTypes = imageUniformTypeTemplate.specialize(specializations);
2553 imageVariables = imageVariablesTemplate.specialize(specializations);
2554 imageLoad = imageLoadTemplate.specialize(specializations);
2556 specializations["image_var_id"] = "%dst_image_ptr";
2557 specializations["image_id"] = "%dst_image";
2558 imageVariables += imageVariablesTemplate.specialize(specializations);
2559 imageLoad += imageLoadTemplate.specialize(specializations);
2563 specializations["image_type_id"] = "%type_src_image";
2564 specializations["image_uni_ptr_type_id"] = "%type_ptr_uniform_const_src_image";
2565 imageTypes = imageTypeTemplate.specialize(specializations);
2566 imageUniformTypes = imageUniformTypeTemplate.specialize(specializations);
2567 imageVariables = imageVariablesTemplate.specialize(specializations);
2568 imageLoad = imageLoadTemplate.specialize(specializations);
2570 specializations["image_format"] = getSpirvFormat(m_writeFormat);
2571 specializations["image_type_id"] = "%type_dst_image";
2572 specializations["image_uni_ptr_type_id"] = "%type_ptr_uniform_const_dst_image";
2573 specializations["image_var_id"] = "%dst_image_ptr";
2574 specializations["image_id"] = "%dst_image";
2575 imageTypes += imageTypeTemplate.specialize(specializations);
2576 imageUniformTypes += imageUniformTypeTemplate.specialize(specializations);
2577 imageVariables += imageVariablesTemplate.specialize(specializations);
2578 imageLoad += imageLoadTemplate.specialize(specializations);
2581 specializations["image_types"] = imageTypes;
2582 specializations["image_uniforms"] = imageUniformTypes;
2583 specializations["image_variables"] = imageVariables;
2584 specializations["image_load"] = imageLoad;
2586 // Specialize whole shader and add it to program collection
2587 programCollection.spirvAsmSources.add("comp") << shaderTemplate.specialize(specializations)
2588 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, spirvVersion, allowSpirv14);
2591 TestInstance* ImageExtendOperandTest::createInstance(Context& context) const
2593 return new ImageExtendOperandTestInstance(context, m_texture, m_readFormat, m_writeFormat, m_relaxedPrecision);
2596 static const Texture s_textures[] =
2598 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1),
2599 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8),
2600 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1),
2601 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8),
2602 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1),
2603 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6),
2604 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2*6),
2605 Texture(IMAGE_TYPE_BUFFER, tcu::IVec3(64, 1, 1), 1),
2608 const Texture& getTestTexture (const ImageType imageType)
2610 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2611 if (s_textures[textureNdx].type() == imageType)
2612 return s_textures[textureNdx];
2614 DE_FATAL("Internal error");
2615 return s_textures[0];
2618 static const VkFormat s_formats[] =
2620 VK_FORMAT_R32G32B32A32_SFLOAT,
2621 VK_FORMAT_R16G16B16A16_SFLOAT,
2622 VK_FORMAT_R32_SFLOAT,
2624 VK_FORMAT_R32G32B32A32_UINT,
2625 VK_FORMAT_R16G16B16A16_UINT,
2626 VK_FORMAT_R8G8B8A8_UINT,
2629 VK_FORMAT_R32G32B32A32_SINT,
2630 VK_FORMAT_R16G16B16A16_SINT,
2631 VK_FORMAT_R8G8B8A8_SINT,
2634 VK_FORMAT_R8G8B8A8_UNORM,
2636 VK_FORMAT_B8G8R8A8_UNORM,
2637 VK_FORMAT_B8G8R8A8_UINT,
2639 VK_FORMAT_R8G8B8A8_SNORM,
2641 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2643 VK_FORMAT_R32G32_SFLOAT,
2644 VK_FORMAT_R16G16_SFLOAT,
2645 VK_FORMAT_R16_SFLOAT,
2647 VK_FORMAT_A2B10G10R10_UINT_PACK32,
2648 VK_FORMAT_R32G32_UINT,
2649 VK_FORMAT_R16G16_UINT,
2651 VK_FORMAT_R8G8_UINT,
2654 VK_FORMAT_R32G32_SINT,
2655 VK_FORMAT_R16G16_SINT,
2657 VK_FORMAT_R8G8_SINT,
2660 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2661 VK_FORMAT_R16G16B16A16_UNORM,
2662 VK_FORMAT_R16G16B16A16_SNORM,
2663 VK_FORMAT_R16G16_UNORM,
2664 VK_FORMAT_R16_UNORM,
2665 VK_FORMAT_R8G8_UNORM,
2668 VK_FORMAT_R16G16_SNORM,
2669 VK_FORMAT_R16_SNORM,
2670 VK_FORMAT_R8G8_SNORM,
2673 VK_FORMAT_R4G4_UNORM_PACK8,
2674 VK_FORMAT_R4G4B4A4_UNORM_PACK16,
2675 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
2676 VK_FORMAT_R5G6B5_UNORM_PACK16,
2677 VK_FORMAT_B5G6R5_UNORM_PACK16,
2678 VK_FORMAT_R5G5B5A1_UNORM_PACK16,
2679 VK_FORMAT_B5G5R5A1_UNORM_PACK16,
2680 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
2681 VK_FORMAT_B8G8R8A8_SNORM,
2682 VK_FORMAT_B8G8R8A8_SINT,
2683 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2684 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2685 VK_FORMAT_A8B8G8R8_UINT_PACK32,
2686 VK_FORMAT_A8B8G8R8_SINT_PACK32,
2687 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2688 VK_FORMAT_A2R10G10B10_SNORM_PACK32,
2689 VK_FORMAT_A2R10G10B10_UINT_PACK32,
2690 VK_FORMAT_A2R10G10B10_SINT_PACK32,
2691 VK_FORMAT_A2B10G10R10_SNORM_PACK32,
2692 VK_FORMAT_A2B10G10R10_SINT_PACK32,
2693 VK_FORMAT_R32G32B32_UINT,
2694 VK_FORMAT_R32G32B32_SINT,
2695 VK_FORMAT_R32G32B32_SFLOAT,
2696 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
2699 static const VkFormat s_formatsThreeComponent[] =
2701 VK_FORMAT_R8G8B8_UINT,
2702 VK_FORMAT_R8G8B8_SINT,
2703 VK_FORMAT_R8G8B8_UNORM,
2704 VK_FORMAT_R8G8B8_SNORM,
2705 VK_FORMAT_R16G16B16_UINT,
2706 VK_FORMAT_R16G16B16_SINT,
2707 VK_FORMAT_R16G16B16_UNORM,
2708 VK_FORMAT_R16G16B16_SNORM,
2709 VK_FORMAT_R16G16B16_SFLOAT,
2710 VK_FORMAT_R32G32B32_UINT,
2711 VK_FORMAT_R32G32B32_SINT,
2712 VK_FORMAT_R32G32B32_SFLOAT,
2717 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
2719 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
2720 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images"));
2721 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images"));
2723 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2725 const Texture& texture = s_textures[textureNdx];
2726 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2727 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2728 const bool isLayered = (texture.numLayers() > 1);
2730 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2732 const bool hasSpirvFmt = hasSpirvFormat(s_formats[formatNdx]);
2736 groupWithFormatByImageViewType->addChild( new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
2737 // Additional tests where the shader uses constant data for imageStore.
2738 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_constant", "", texture, s_formats[formatNdx], StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER | StoreTest::FLAG_STORE_CONSTANT_VALUE));
2740 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0));
2742 if (isLayered && hasSpirvFmt)
2743 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2744 texture, s_formats[formatNdx],
2745 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2747 if (texture.type() == IMAGE_TYPE_BUFFER)
2750 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2751 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN));
2755 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2756 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2759 testGroup->addChild(testGroupWithFormat.release());
2760 testGroup->addChild(testGroupWithoutFormat.release());
2762 return testGroup.release();
2765 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
2767 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
2768 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2769 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2771 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2773 const Texture& texture = s_textures[textureNdx];
2774 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2775 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2776 const bool isLayered = (texture.numLayers() > 1);
2778 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2780 // These tests always require a SPIR-V format for the write image, even if the read
2781 // image is being used without a format.
2782 if (!hasSpirvFormat(s_formats[formatNdx]))
2785 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx]));
2786 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0));
2789 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2790 texture, s_formats[formatNdx], s_formats[formatNdx],
2791 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2792 if (texture.type() == IMAGE_TYPE_BUFFER)
2794 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2795 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign_uniform", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2796 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN));
2797 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign_uniform", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2801 if (texture.type() == IMAGE_TYPE_BUFFER)
2803 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formatsThreeComponent); ++formatNdx)
2805 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formatsThreeComponent[formatNdx]) + "_uniform", "", texture, s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2806 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formatsThreeComponent[formatNdx]) + "_minalign_uniform", "", texture, s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2810 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2811 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2814 testGroup->addChild(testGroupWithFormat.release());
2815 testGroup->addChild(testGroupWithoutFormat.release());
2817 return testGroup.release();
2820 tcu::TestCaseGroup* createImageLoadStoreLodAMDTests (tcu::TestContext& testCtx)
2822 static const Texture textures[] =
2824 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8, 1, 6),
2825 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1, 1, 6),
2826 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1, 1, 6),
2827 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8, 1, 6),
2828 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1, 1, 6),
2829 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6, 1, 6),
2830 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2*6, 1, 6),
2833 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_lod", "Cases with imageLoad() followed by imageStore()"));
2834 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2835 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2837 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(textures); ++textureNdx)
2839 const Texture& texture = textures[textureNdx];
2840 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2841 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2842 const bool isLayered = (texture.numLayers() > 1);
2844 if (texture.type() == IMAGE_TYPE_BUFFER)
2847 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2849 // These tests always require a SPIR-V format for the write image, even if the read
2850 // image is being used without a format.
2851 if (!hasSpirvFormat(s_formats[formatNdx]))
2854 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER, DE_TRUE));
2855 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0, DE_TRUE));
2858 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2859 texture, s_formats[formatNdx], s_formats[formatNdx],
2860 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER, DE_TRUE));
2863 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2864 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2867 testGroup->addChild(testGroupWithFormat.release());
2868 testGroup->addChild(testGroupWithoutFormat.release());
2870 return testGroup.release();
2873 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
2875 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats"));
2877 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2879 const Texture& texture = s_textures[textureNdx];
2880 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2882 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
2883 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2885 if (!hasSpirvFormat(s_formats[formatNdx]))
2888 const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
2889 if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
2890 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
2892 testGroup->addChild(groupByImageViewType.release());
2895 return testGroup.release();
2898 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
2900 const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
2901 const Texture& texture = getTestTexture(imageType);
2902 return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2908 bool relaxedOK(VkFormat format)
2910 tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(format));
2911 int maxBitDepth = deMax32(deMax32(bitDepth[0], bitDepth[1]), deMax32(bitDepth[2], bitDepth[3]));
2912 return maxBitDepth <= 16;
2915 // Get a format used for reading or writing in extension operand tests. These formats allow representing the shader sampled type to
2916 // verify results from read or write operations.
2917 VkFormat getShaderExtensionOperandFormat (bool isSigned, bool is64Bit)
2919 const VkFormat formats[] =
2921 VK_FORMAT_R32G32B32A32_UINT,
2922 VK_FORMAT_R32G32B32A32_SINT,
2926 return formats[2u * (is64Bit ? 1u : 0u) + (isSigned ? 1u : 0u)];
2929 // INT or UINT format?
2930 bool isIntegralFormat (VkFormat format)
2932 return (isIntFormat(format) || isUintFormat(format));
2935 // Return the list of formats used for the extension operand tests (SignExten/ZeroExtend).
2936 std::vector<VkFormat> getExtensionOperandFormatList (void)
2938 std::vector<VkFormat> formatList;
2940 for (auto format : s_formats)
2942 if (isIntegralFormat(format))
2943 formatList.push_back(format);
2946 formatList.push_back(VK_FORMAT_R64_SINT);
2947 formatList.push_back(VK_FORMAT_R64_UINT);
2954 tcu::TestCaseGroup* createImageExtendOperandsTests(tcu::TestContext& testCtx)
2956 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
2958 GroupPtr testGroup(new tcu::TestCaseGroup(testCtx, "extend_operands_spirv1p4", "Cases with SignExtend and ZeroExtend"));
2962 ExtendTestType testType;
2966 { ExtendTestType::READ, "read" },
2967 { ExtendTestType::WRITE, "write" },
2970 const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
2971 const auto formatList = getExtensionOperandFormatList();
2973 for (const auto format : formatList)
2975 const auto isInt = isIntFormat(format);
2976 const auto isUint = isUintFormat(format);
2977 const auto use64Bits = is64BitIntegerFormat(format);
2979 DE_ASSERT(isInt || isUint);
2981 GroupPtr formatGroup (new tcu::TestCaseGroup(testCtx, getFormatShortString(format).c_str(), ""));
2983 for (const auto& testType : testTypes)
2985 GroupPtr testTypeGroup (new tcu::TestCaseGroup(testCtx, testType.name, ""));
2987 for (int match = 0; match < 2; ++match)
2989 const bool mismatched = (match == 1);
2990 const char* matchGroupName = (mismatched ? "mismatched_sign" : "matched_sign");
2992 // SPIR-V does not allow this kind of sampled type override.
2993 if (mismatched && isUint)
2996 GroupPtr matchGroup (new tcu::TestCaseGroup(testCtx, matchGroupName, ""));
2998 for (int prec = 0; prec < 2; prec++)
3000 const bool relaxedPrecision = (prec != 0);
3002 const char* precisionName = (relaxedPrecision ? "relaxed_precision" : "normal_precision");
3003 const auto signedOther = ((isInt && !mismatched) || (isUint && mismatched));
3004 const auto otherFormat = getShaderExtensionOperandFormat(signedOther, use64Bits);
3005 const auto readFormat = (testType.testType == ExtendTestType::READ ? format : otherFormat);
3006 const auto writeFormat = (testType.testType == ExtendTestType::WRITE ? format : otherFormat);
3008 if (relaxedPrecision && !relaxedOK(readFormat))
3011 if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
3014 matchGroup->addChild(new ImageExtendOperandTest(testCtx, precisionName, texture, readFormat, writeFormat, mismatched, relaxedPrecision, testType.testType));
3017 testTypeGroup->addChild(matchGroup.release());
3020 formatGroup->addChild(testTypeGroup.release());
3023 testGroup->addChild(formatGroup.release());
3026 return testGroup.release();
3029 tcu::TestCaseGroup* createImageNontemporalOperandTests(tcu::TestContext& testCtx)
3031 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "nontemporal_operand", "Cases with Nontemporal image operand for SPOIR-V 1.6"));
3033 const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
3035 // using just integer formats for tests so that ImageExtendOperandTest could be reused
3036 const auto formatList = getExtensionOperandFormatList();
3038 for (const auto format : formatList)
3040 const std::string caseName = getFormatShortString(format);
3041 const auto readFormat = format;
3042 const auto writeFormat = getShaderExtensionOperandFormat(isIntFormat(format), is64BitIntegerFormat(format));
3044 if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
3047 // note: just testing OpImageWrite as OpImageRead is tested with addComputeImageSamplerTest
3048 testGroup->addChild(new ImageExtendOperandTest(testCtx, caseName, texture,
3049 readFormat, writeFormat, false, false, ExtendTestType::WRITE_NONTEMPORAL));
3052 return testGroup.release();