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 "tcuStringTemplate.hpp"
54 #include "tcuVectorUtil.hpp"
69 // Check for three-component (non-packed) format, i.e. pixel size is a multiple of 3.
70 bool formatHasThreeComponents(VkFormat format)
72 const tcu::TextureFormat texFormat = mapVkFormat(format);
73 return (getPixelSize(texFormat) % 3) == 0;
76 VkFormat getSingleComponentFormat(VkFormat format)
78 tcu::TextureFormat texFormat = mapVkFormat(format);
79 texFormat = tcu::TextureFormat(tcu::TextureFormat::R, texFormat.type);
80 return mapTextureFormat(texFormat);
83 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
85 return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
88 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
90 switch (texture.type())
94 case IMAGE_TYPE_BUFFER:
96 DE_ASSERT(layer == 0);
99 case IMAGE_TYPE_1D_ARRAY:
100 return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
102 case IMAGE_TYPE_2D_ARRAY:
103 case IMAGE_TYPE_CUBE:
104 case IMAGE_TYPE_CUBE_ARRAY:
105 case IMAGE_TYPE_3D: // 3d texture is treated as if depth was the layers
106 return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
109 DE_FATAL("Internal test error");
110 return tcu::ConstPixelBufferAccess();
114 //! \return the size in bytes of a given level of a mipmap image, including array layers.
115 vk::VkDeviceSize getMipmapLevelImageSizeBytes (const Texture& texture, const vk::VkFormat format, const deUint32 mipmapLevel)
117 tcu::IVec3 size = texture.size(mipmapLevel);
118 return tcu::getPixelSize(vk::mapVkFormat(format)) * size.x() * size.y() * size.z();
121 //! \return the size in bytes of the whole mipmap image, including all mipmap levels and array layers
122 vk::VkDeviceSize getMipmapImageTotalSizeBytes (const Texture& texture, const vk::VkFormat format)
124 vk::VkDeviceSize size = 0u;
125 deInt32 levelCount = 0u;
129 size += getMipmapLevelImageSizeBytes(texture, format, levelCount);
131 } while (levelCount < texture.numMipmapLevels());
135 //! \return true if all layers match in both pixel buffers
136 bool comparePixelBuffers (tcu::TestLog& log,
137 const Texture& texture,
138 const VkFormat format,
139 const tcu::ConstPixelBufferAccess reference,
140 const tcu::ConstPixelBufferAccess result,
141 const deUint32 mipmapLevel = 0u)
143 DE_ASSERT(reference.getFormat() == result.getFormat());
144 DE_ASSERT(reference.getSize() == result.getSize());
146 const bool is3d = (texture.type() == IMAGE_TYPE_3D);
147 const int numLayersOrSlices = (is3d ? texture.size(mipmapLevel).z() : texture.numLayers());
148 const int numCubeFaces = 6;
150 int passedLayers = 0;
151 for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
153 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
154 const std::string comparisonDesc = "Image Comparison, " +
155 (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
156 is3d ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx) + " , level " + de::toString(mipmapLevel));
158 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
159 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
163 switch (tcu::getTextureChannelClass(mapVkFormat(format).type))
165 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
166 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
168 ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
172 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
174 // Allow error of minimum representable difference
175 const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()) - 1u).cast<float>());
177 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
181 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
183 const tcu::UVec4 bitDepth = tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u;
184 // To avoid bit-shifting with negative value, which is undefined behaviour.
185 const tcu::UVec4 fixedBitDepth = tcu::select(bitDepth, tcu::UVec4(0u, 0u, 0u, 0u), tcu::greaterThanEqual(bitDepth.cast<deInt32>(), tcu::IVec4(0, 0, 0, 0)));
187 // Allow error of minimum representable difference
188 const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << fixedBitDepth) - 1u).cast<float>());
190 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
194 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
196 // Convert target format ulps to float ulps and allow 1 ulp difference
197 const tcu::UVec4 threshold (tcu::UVec4(1u) << (tcu::UVec4(23) - tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()));
199 ok = tcu::floatUlpThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
204 DE_FATAL("Unknown channel class");
211 return passedLayers == numLayersOrSlices;
214 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
215 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
217 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
219 for (int z = 0; z < access.getDepth(); ++z)
220 for (int y = 0; y < access.getHeight(); ++y)
221 for (int x = 0; x < access.getWidth(); ++x)
223 const tcu::Vec4 color(access.getPixel(x, y, z));
224 tcu::Vec4 newColor = color;
226 for (int i = 0; i < 4; ++i)
228 if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
230 const tcu::Float16 f(color[i]);
231 if (f.isDenorm() || f.isInf() || f.isNaN())
236 const tcu::Float32 f(color[i]);
237 if (f.isDenorm() || f.isInf() || f.isNaN())
242 if (newColor != color)
243 access.setPixel(newColor, x, y, z);
247 //!< replace invalid pixels in the image (-128)
248 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
250 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
252 for (int z = 0; z < access.getDepth(); ++z)
253 for (int y = 0; y < access.getHeight(); ++y)
254 for (int x = 0; x < access.getWidth(); ++x)
256 const tcu::IVec4 color(access.getPixelInt(x, y, z));
257 tcu::IVec4 newColor = color;
259 for (int i = 0; i < 4; ++i)
261 const deInt32 oldColor(color[i]);
262 if (oldColor == -128) newColor[i] = -127;
265 if (newColor != color)
266 access.setPixel(newColor, x, y, z);
270 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat)
272 // Generate a reference image data using the storage format
274 tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
275 const tcu::PixelBufferAccess access = reference.getAccess();
277 const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
278 const float storeColorBias = computeStoreColorBias(imageFormat);
280 const bool intFormat = isIntegerFormat(imageFormat);
281 const bool storeNegativeValues = isSignedFormat(imageFormat) && (storeColorBias == 0);
282 const int xMax = imageSize.x() - 1;
283 const int yMax = imageSize.y() - 1;
285 for (int z = 0; z < imageSize.z(); ++z)
286 for (int y = 0; y < imageSize.y(); ++y)
287 for (int x = 0; x < imageSize.x(); ++x)
289 tcu::IVec4 color(x^y^z, (xMax - x)^y^z, x^(yMax - y)^z, (xMax - x)^(yMax - y)^z);
291 if (storeNegativeValues)
292 color -= tcu::IVec4(deRoundFloatToInt32((float)de::max(xMax, yMax) / 2.0f));
295 access.setPixel(color, x, y, z);
297 access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z);
300 // If the image is to be accessed as a float texture, get rid of invalid values
302 if (isFloatFormat(readFormat) && imageFormat != readFormat)
303 replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
304 if (isSnormFormat(readFormat) && imageFormat != readFormat)
305 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
310 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat)
312 return generateReferenceImage(imageSize, imageFormat, imageFormat);
315 void flipHorizontally (const tcu::PixelBufferAccess access)
317 const int xMax = access.getWidth() - 1;
318 const int halfWidth = access.getWidth() / 2;
320 if (isIntegerFormat(mapTextureFormat(access.getFormat())))
321 for (int z = 0; z < access.getDepth(); z++)
322 for (int y = 0; y < access.getHeight(); y++)
323 for (int x = 0; x < halfWidth; x++)
325 const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
326 access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
327 access.setPixel(temp, x, y, z);
330 for (int z = 0; z < access.getDepth(); z++)
331 for (int y = 0; y < access.getHeight(); y++)
332 for (int x = 0; x < halfWidth; x++)
334 const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
335 access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
336 access.setPixel(temp, x, y, z);
340 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
342 return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
345 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
347 const DeviceInterface& vk = context.getDeviceInterface();
349 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
350 const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
351 VK_ACCESS_SHADER_WRITE_BIT, 0u,
352 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
353 image, fullImageSubresourceRange);
355 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);
358 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
360 const DeviceInterface& vk = context.getDeviceInterface();
362 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
363 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
364 buffer, 0ull, bufferSizeBytes);
366 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);
369 //! Copy all layers of an image to a buffer.
370 void commandCopyImageToBuffer (Context& context,
371 const VkCommandBuffer cmdBuffer,
373 const VkBuffer buffer,
374 const VkDeviceSize bufferSizeBytes,
375 const Texture& texture)
377 const DeviceInterface& vk = context.getDeviceInterface();
379 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
380 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
381 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
382 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
383 image, fullImageSubresourceRange);
385 const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
387 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
388 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
389 buffer, 0ull, bufferSizeBytes);
391 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);
392 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ©Region);
393 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);
396 //! Copy all layers of a mipmap image to a buffer.
397 void commandCopyMipmapImageToBuffer (Context& context,
398 const VkCommandBuffer cmdBuffer,
400 const VkFormat imageFormat,
401 const VkBuffer buffer,
402 const VkDeviceSize bufferSizeBytes,
403 const Texture& texture)
405 const DeviceInterface& vk = context.getDeviceInterface();
407 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
408 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
409 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
410 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
411 image, fullImageSubresourceRange);
413 std::vector<VkBufferImageCopy> copyRegions;
414 VkDeviceSize bufferOffset = 0u;
415 for (deInt32 levelNdx = 0; levelNdx < texture.numMipmapLevels(); levelNdx++)
417 const VkBufferImageCopy copyParams =
419 bufferOffset, // VkDeviceSize bufferOffset;
420 0u, // deUint32 bufferRowLength;
421 0u, // deUint32 bufferImageHeight;
422 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
423 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
424 makeExtent3D(texture.layerSize(levelNdx)), // VkExtent3D imageExtent;
426 copyRegions.push_back(copyParams);
427 bufferOffset += getMipmapLevelImageSizeBytes(texture, imageFormat, levelNdx);
430 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
431 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
432 buffer, 0ull, bufferSizeBytes);
434 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);
435 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, (deUint32) copyRegions.size(), copyRegions.data());
436 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);
439 class StoreTest : public TestCase
444 FLAG_SINGLE_LAYER_BIND = 0x1, //!< Run the shader multiple times, each time binding a different layer.
445 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 0x2, //!< Declare the format of the images in the shader code
446 FLAG_MINALIGN = 0x4, //!< Use bufferview offset that matches the advertised minimum alignment
449 StoreTest (tcu::TestContext& testCtx,
450 const std::string& name,
451 const std::string& description,
452 const Texture& texture,
453 const VkFormat format,
454 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
456 virtual void checkSupport (Context& context) const;
457 void initPrograms (SourceCollections& programCollection) const;
458 TestInstance* createInstance (Context& context) const;
461 const Texture m_texture;
462 const VkFormat m_format;
463 const bool m_declareImageFormatInShader;
464 const bool m_singleLayerBind;
465 const bool m_minalign;
468 StoreTest::StoreTest (tcu::TestContext& testCtx,
469 const std::string& name,
470 const std::string& description,
471 const Texture& texture,
472 const VkFormat format,
473 const deUint32 flags)
474 : TestCase (testCtx, name, description)
475 , m_texture (texture)
477 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
478 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
479 , m_minalign ((flags & FLAG_MINALIGN) != 0)
481 if (m_singleLayerBind)
482 DE_ASSERT(m_texture.numLayers() > 1);
485 void StoreTest::checkSupport (Context& context) const
487 const VkFormatProperties3 formatProperties (context.getFormatProperties(m_format));
489 if (!m_declareImageFormatInShader && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
490 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage buffer");
492 if (!m_declareImageFormatInShader && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
493 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage images");
495 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
496 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
498 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
499 TCU_THROW(NotSupportedError, "Format not supported for storage images");
501 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
502 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
505 void StoreTest::initPrograms (SourceCollections& programCollection) const
507 const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
508 const float storeColorBias = computeStoreColorBias(m_format);
509 DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
511 const deUint32 xMax = m_texture.size().x() - 1;
512 const deUint32 yMax = m_texture.size().y() - 1;
513 const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
514 const bool storeNegativeValues = isSignedFormat(m_format) && (storeColorBias == 0);
515 bool useClamp = false;
516 std::string colorBaseExpr = signednessPrefix + "vec4("
518 + "(" + de::toString(xMax) + "-gx)^gy^gz, "
519 + "gx^(" + de::toString(yMax) + "-gy)^gz, "
520 + "(" + de::toString(xMax) + "-gx)^(" + de::toString(yMax) + "-gy)^gz)";
522 // Large integer values may not be represented with formats with low bit depths
523 if (isIntegerFormat(m_format))
525 const deInt64 minStoreValue = storeNegativeValues ? 0 - deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : 0;
526 const deInt64 maxStoreValue = storeNegativeValues ? deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : de::max(xMax, yMax);
528 useClamp = !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(minStoreValue), mapVkFormat(m_format)) ||
529 !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(maxStoreValue), mapVkFormat(m_format));
532 // Clamp if integer value cannot be represented with the current format
535 const tcu::IVec4 bitDepths = tcu::getTextureFormatBitDepth(mapVkFormat(m_format));
536 tcu::IVec4 minRepresentableValue;
537 tcu::IVec4 maxRepresentableValue;
539 switch (tcu::getTextureChannelClass(mapVkFormat(m_format).type))
541 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
543 minRepresentableValue = tcu::IVec4(0);
544 maxRepresentableValue = (tcu::IVec4(1) << bitDepths) - tcu::IVec4(1);
548 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
550 minRepresentableValue = -(tcu::IVec4(1) << bitDepths - tcu::IVec4(1));
551 maxRepresentableValue = (tcu::IVec4(1) << (bitDepths - tcu::IVec4(1))) - tcu::IVec4(1);
556 DE_ASSERT(isIntegerFormat(m_format));
559 colorBaseExpr = "clamp(" + colorBaseExpr + ", "
560 + signednessPrefix + "vec4" + de::toString(minRepresentableValue) + ", "
561 + signednessPrefix + "vec4" + de::toString(maxRepresentableValue) + ")";
564 std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
565 + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
567 if (storeNegativeValues)
568 colorExpr += "-" + de::toString(deRoundFloatToInt32((float)deMax32(xMax, yMax) / 2.0f));
570 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
571 const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
573 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
574 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
576 std::ostringstream src;
577 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
579 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
580 if (m_declareImageFormatInShader)
582 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
583 src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
586 src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n";
588 if (m_singleLayerBind)
589 src << "layout (binding = 1) readonly uniform Constants {\n"
590 << " int u_layerNdx;\n"
594 << "void main (void)\n"
596 << " int gx = int(gl_GlobalInvocationID.x);\n"
597 << " int gy = int(gl_GlobalInvocationID.y);\n"
598 << " int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
599 << " imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
602 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
605 //! Generic test iteration algorithm for image tests
606 class BaseTestInstance : public TestInstance
609 BaseTestInstance (Context& context,
610 const Texture& texture,
611 const VkFormat format,
612 const bool declareImageFormatInShader,
613 const bool singleLayerBind,
615 const bool bufferLoadUniform);
617 tcu::TestStatus iterate (void);
619 virtual ~BaseTestInstance (void) {}
622 virtual VkDescriptorSetLayout prepareDescriptors (void) = 0;
623 virtual tcu::TestStatus verifyResult (void) = 0;
625 virtual void commandBeforeCompute (const VkCommandBuffer cmdBuffer) = 0;
626 virtual void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer) = 0;
627 virtual void commandAfterCompute (const VkCommandBuffer cmdBuffer) = 0;
629 virtual void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
630 const VkPipelineLayout pipelineLayout,
631 const int layerNdx) = 0;
632 virtual deUint32 getViewOffset (Context& context,
633 const VkFormat format,
636 const Texture m_texture;
637 const VkFormat m_format;
638 const bool m_declareImageFormatInShader;
639 const bool m_singleLayerBind;
640 const bool m_minalign;
641 const bool m_bufferLoadUniform;
642 const deUint32 m_srcViewOffset;
643 const deUint32 m_dstViewOffset;
646 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign, const bool bufferLoadUniform)
647 : TestInstance (context)
648 , m_texture (texture)
650 , m_declareImageFormatInShader (declareImageFormatInShader)
651 , m_singleLayerBind (singleLayerBind)
652 , m_minalign (minalign)
653 , m_bufferLoadUniform (bufferLoadUniform)
654 , m_srcViewOffset (getViewOffset(context, format, m_bufferLoadUniform))
655 , m_dstViewOffset (getViewOffset(context, formatHasThreeComponents(format) ? getSingleComponentFormat(format) : format, false))
659 tcu::TestStatus BaseTestInstance::iterate (void)
661 const DeviceInterface& vk = m_context.getDeviceInterface();
662 const VkDevice device = m_context.getDevice();
663 const VkQueue queue = m_context.getUniversalQueue();
664 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
666 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
668 const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
669 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
670 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
672 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
673 const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
675 beginCommandBuffer(vk, *cmdBuffer);
677 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
678 commandBeforeCompute(*cmdBuffer);
680 const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
681 const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
682 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
684 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
687 commandBetweenShaderInvocations(*cmdBuffer);
689 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
692 commandAfterCompute(*cmdBuffer);
694 endCommandBuffer(vk, *cmdBuffer);
696 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
698 return verifyResult();
701 //! Base store test implementation
702 class StoreTestInstance : public BaseTestInstance
705 StoreTestInstance (Context& context,
706 const Texture& texture,
707 const VkFormat format,
708 const bool declareImageFormatInShader,
709 const bool singleLayerBind,
710 const bool minalign);
713 virtual tcu::TestStatus verifyResult (void);
715 // Add empty implementations for functions that might be not needed
716 void commandBeforeCompute (const VkCommandBuffer) {}
717 void commandBetweenShaderInvocations (const VkCommandBuffer) {}
718 void commandAfterCompute (const VkCommandBuffer) {}
720 de::MovePtr<Buffer> m_imageBuffer;
721 const VkDeviceSize m_imageSizeBytes;
724 deUint32 BaseTestInstance::getViewOffset(Context& context,
725 const VkFormat format,
730 if (!context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
731 return (deUint32)context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
733 VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties;
734 deMemset(&alignmentProperties, 0, sizeof(alignmentProperties));
735 alignmentProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
737 VkPhysicalDeviceProperties2 properties2;
738 deMemset(&properties2, 0, sizeof(properties2));
739 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
740 properties2.pNext = &alignmentProperties;
742 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
744 VkBool32 singleTexelAlignment = uniform ? alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
745 alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
746 VkDeviceSize align = uniform ? alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
747 alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
749 VkDeviceSize texelSize = formatHasThreeComponents(format) ? tcu::getChannelSize(vk::mapVkFormat(format).type) : tcu::getPixelSize(vk::mapVkFormat(format));
751 if (singleTexelAlignment)
752 align = de::min(align, texelSize);
754 return (deUint32)align;
760 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign)
761 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, false)
762 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format))
764 const DeviceInterface& vk = m_context.getDeviceInterface();
765 const VkDevice device = m_context.getDevice();
766 Allocator& allocator = m_context.getDefaultAllocator();
768 // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
770 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
771 vk, device, allocator,
772 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
773 MemoryRequirement::HostVisible));
776 tcu::TestStatus StoreTestInstance::verifyResult (void)
778 const DeviceInterface& vk = m_context.getDeviceInterface();
779 const VkDevice device = m_context.getDevice();
781 const tcu::IVec3 imageSize = m_texture.size();
782 const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format);
784 const Allocation& alloc = m_imageBuffer->getAllocation();
785 invalidateAlloc(vk, device, alloc);
786 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, (const char *)alloc.getHostPtr() + m_dstViewOffset);
788 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
789 return tcu::TestStatus::pass("Passed");
791 return tcu::TestStatus::fail("Image comparison failed");
794 //! Store test for images
795 class ImageStoreTestInstance : public StoreTestInstance
798 ImageStoreTestInstance (Context& context,
799 const Texture& texture,
800 const VkFormat format,
801 const bool declareImageFormatInShader,
802 const bool singleLayerBind,
803 const bool minalign);
806 VkDescriptorSetLayout prepareDescriptors (void);
807 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
808 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
809 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
811 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
812 const VkPipelineLayout pipelineLayout,
815 de::MovePtr<Image> m_image;
816 de::MovePtr<Buffer> m_constantsBuffer;
817 const VkDeviceSize m_constantsBufferChunkSizeBytes;
818 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
819 Move<VkDescriptorPool> m_descriptorPool;
820 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
821 std::vector<SharedVkImageView> m_allImageViews;
824 ImageStoreTestInstance::ImageStoreTestInstance (Context& context,
825 const Texture& texture,
826 const VkFormat format,
827 const bool declareImageFormatInShader,
828 const bool singleLayerBind,
830 : StoreTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign)
831 , m_constantsBufferChunkSizeBytes (getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32)))
832 , m_allDescriptorSets (texture.numLayers())
833 , m_allImageViews (texture.numLayers())
835 const DeviceInterface& vk = m_context.getDeviceInterface();
836 const VkDevice device = m_context.getDevice();
837 Allocator& allocator = m_context.getDefaultAllocator();
839 m_image = de::MovePtr<Image>(new Image(
840 vk, device, allocator,
841 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
842 MemoryRequirement::Any));
844 // This buffer will be used to pass constants to the shader
846 const int numLayers = m_texture.numLayers();
847 const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
848 m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
849 vk, device, allocator,
850 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
851 MemoryRequirement::HostVisible));
854 const Allocation& alloc = m_constantsBuffer->getAllocation();
855 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
857 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
859 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
861 deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
862 *valuePtr = static_cast<deUint32>(layerNdx);
865 flushAlloc(vk, device, alloc);
869 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
871 const DeviceInterface& vk = m_context.getDeviceInterface();
872 const VkDevice device = m_context.getDevice();
874 const int numLayers = m_texture.numLayers();
875 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
876 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
877 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
880 m_descriptorPool = DescriptorPoolBuilder()
881 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
882 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
883 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
885 if (m_singleLayerBind)
887 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
889 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
890 m_allImageViews[layerNdx] = makeVkSharedPtr(makeImageView(
891 vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
892 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
895 else // bind all layers at once
897 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
898 m_allImageViews[0] = makeVkSharedPtr(makeImageView(
899 vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
900 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
903 return *m_descriptorSetLayout; // not passing the ownership
906 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
908 const DeviceInterface& vk = m_context.getDeviceInterface();
909 const VkDevice device = m_context.getDevice();
911 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
912 const VkImageView imageView = **m_allImageViews[layerNdx];
914 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
916 // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
917 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
918 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
920 DescriptorSetUpdateBuilder()
921 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
922 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
924 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
927 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
929 const DeviceInterface& vk = m_context.getDeviceInterface();
931 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
932 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
933 0u, VK_ACCESS_SHADER_WRITE_BIT,
934 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
935 m_image->get(), fullImageSubresourceRange);
937 const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
938 const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
939 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
940 m_constantsBuffer->get(), 0ull, constantsBufferSize);
942 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);
945 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
947 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
950 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
952 commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
955 //! Store test for buffers
956 class BufferStoreTestInstance : public StoreTestInstance
959 BufferStoreTestInstance (Context& context,
960 const Texture& texture,
961 const VkFormat format,
962 const bool declareImageFormatInShader,
963 const bool minalign);
966 VkDescriptorSetLayout prepareDescriptors (void);
967 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
969 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
970 const VkPipelineLayout pipelineLayout,
973 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
974 Move<VkDescriptorPool> m_descriptorPool;
975 Move<VkDescriptorSet> m_descriptorSet;
976 Move<VkBufferView> m_bufferView;
979 BufferStoreTestInstance::BufferStoreTestInstance (Context& context,
980 const Texture& texture,
981 const VkFormat format,
982 const bool declareImageFormatInShader,
984 : StoreTestInstance(context, texture, format, declareImageFormatInShader, false, minalign)
988 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
990 const DeviceInterface& vk = m_context.getDeviceInterface();
991 const VkDevice device = m_context.getDevice();
993 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
994 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
997 m_descriptorPool = DescriptorPoolBuilder()
998 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
999 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1001 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1002 m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_dstViewOffset, m_imageSizeBytes);
1004 return *m_descriptorSetLayout; // not passing the ownership
1007 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1009 DE_ASSERT(layerNdx == 0);
1012 const VkDevice device = m_context.getDevice();
1013 const DeviceInterface& vk = m_context.getDeviceInterface();
1015 DescriptorSetUpdateBuilder()
1016 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
1017 .update(vk, device);
1018 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1021 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1023 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes + m_dstViewOffset);
1026 class LoadStoreTest : public TestCase
1031 FLAG_SINGLE_LAYER_BIND = 1 << 0, //!< Run the shader multiple times, each time binding a different layer.
1032 FLAG_RESTRICT_IMAGES = 1 << 1, //!< If given, images in the shader will be qualified with "restrict".
1033 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 1 << 2, //!< Declare the format of the images in the shader code
1034 FLAG_MINALIGN = 1 << 3, //!< Use bufferview offset that matches the advertised minimum alignment
1035 FLAG_UNIFORM_TEXEL_BUFFER = 1 << 4, //!< Load from a uniform texel buffer rather than a storage texel buffer
1038 LoadStoreTest (tcu::TestContext& testCtx,
1039 const std::string& name,
1040 const std::string& description,
1041 const Texture& texture,
1042 const VkFormat format,
1043 const VkFormat imageFormat,
1044 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER,
1045 const deBool imageLoadStoreLodAMD = DE_FALSE);
1047 virtual void checkSupport (Context& context) const;
1048 void initPrograms (SourceCollections& programCollection) const;
1049 TestInstance* createInstance (Context& context) const;
1052 const Texture m_texture;
1053 const VkFormat m_format; //!< Format as accessed in the shader
1054 const VkFormat m_imageFormat; //!< Storage format
1055 const bool m_declareImageFormatInShader; //!< Whether the shader will specify the format layout qualifier of the images
1056 const bool m_singleLayerBind;
1057 const bool m_restrictImages;
1058 const bool m_minalign;
1059 bool m_bufferLoadUniform;
1060 const deBool m_imageLoadStoreLodAMD;
1063 LoadStoreTest::LoadStoreTest (tcu::TestContext& testCtx,
1064 const std::string& name,
1065 const std::string& description,
1066 const Texture& texture,
1067 const VkFormat format,
1068 const VkFormat imageFormat,
1069 const deUint32 flags,
1070 const deBool imageLoadStoreLodAMD)
1071 : TestCase (testCtx, name, description)
1072 , m_texture (texture)
1074 , m_imageFormat (imageFormat)
1075 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
1076 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
1077 , m_restrictImages ((flags & FLAG_RESTRICT_IMAGES) != 0)
1078 , m_minalign ((flags & FLAG_MINALIGN) != 0)
1079 , m_bufferLoadUniform ((flags & FLAG_UNIFORM_TEXEL_BUFFER) != 0)
1080 , m_imageLoadStoreLodAMD (imageLoadStoreLodAMD)
1082 if (m_singleLayerBind)
1083 DE_ASSERT(m_texture.numLayers() > 1);
1085 DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
1088 void LoadStoreTest::checkSupport (Context& context) const
1090 const VkFormatProperties3 formatProperties (context.getFormatProperties(m_format));
1091 const VkFormatProperties3 imageFormatProperties (context.getFormatProperties(m_imageFormat));
1093 if (m_imageLoadStoreLodAMD)
1094 context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1096 if (!m_bufferLoadUniform && !m_declareImageFormatInShader && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR))
1097 TCU_THROW(NotSupportedError, "Format not supported for unformatted loads via storage images");
1099 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1100 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1102 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1103 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1105 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1106 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1108 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageFormatProperties.optimalTilingFeatures))
1109 TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1111 if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1112 TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1114 if (formatHasThreeComponents(m_format))
1116 // When the source buffer is three-component, the destination buffer is single-component.
1117 VkFormat dstFormat = getSingleComponentFormat(m_format);
1118 const VkFormatProperties3 dstFormatProperties (context.getFormatProperties(dstFormat));
1120 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1121 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1124 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1125 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1127 if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1128 TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1131 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
1133 const tcu::TextureFormat texFormat = mapVkFormat(m_format);
1134 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
1135 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
1136 const std::string formatQualifierStr = getShaderImageFormatQualifier(texFormat);
1137 const std::string uniformTypeStr = getFormatPrefix(texFormat) + "textureBuffer";
1138 const std::string imageTypeStr = getShaderImageType(texFormat, usedImageType);
1139 const std::string maybeRestrictStr = (m_restrictImages ? "restrict " : "");
1140 const std::string xMax = de::toString(m_texture.size().x() - 1);
1142 std::ostringstream src;
1143 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1145 if (!m_declareImageFormatInShader)
1147 src << "#extension GL_EXT_shader_image_load_formatted : require\n";
1150 if (m_imageLoadStoreLodAMD)
1152 src << "#extension GL_AMD_shader_image_load_store_lod : require\n";
1155 src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
1156 if (m_bufferLoadUniform)
1157 src << "layout (binding = 0) uniform " << uniformTypeStr << " u_image0;\n";
1158 else if (m_declareImageFormatInShader)
1159 src << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1161 src << "layout (binding = 0) " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1163 if (formatHasThreeComponents(m_format))
1164 src << "layout (binding = 1) " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1166 src << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1169 << "void main (void)\n"
1173 default: DE_ASSERT(0); // fallthrough
1175 if (m_bufferLoadUniform)
1177 // for three-component formats, the dst buffer is single-component and the shader
1178 // expands the store into 3 component-wise stores.
1179 std::string type = getFormatPrefix(texFormat) + "vec4";
1180 src << " int pos = int(gl_GlobalInvocationID.x);\n"
1181 " " << type << " t = texelFetch(u_image0, " + xMax + "-pos);\n";
1182 if (formatHasThreeComponents(m_format))
1184 src << " imageStore(u_image1, 3*pos+0, " << type << "(t.x));\n";
1185 src << " imageStore(u_image1, 3*pos+1, " << type << "(t.y));\n";
1186 src << " imageStore(u_image1, 3*pos+2, " << type << "(t.z));\n";
1189 src << " imageStore(u_image1, pos, t);\n";
1191 else if (m_imageLoadStoreLodAMD)
1194 " int pos = int(gl_GlobalInvocationID.x);\n";
1196 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1198 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1199 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, " + xMaxSize + "-pos, " + de::toString(levelNdx) + "));\n";
1205 " int pos = int(gl_GlobalInvocationID.x);\n"
1206 " imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n";
1210 if (m_imageLoadStoreLodAMD)
1212 src << " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
1214 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1216 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1217 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec2(" + xMaxSize + "-pos.x, pos.y), " + de::toString(levelNdx) + "));\n";
1224 " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
1225 " imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n";
1229 if (m_imageLoadStoreLodAMD)
1231 src << " ivec3 pos = ivec3(gl_GlobalInvocationID);\n";
1233 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1235 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1236 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec3(" + xMaxSize + "-pos.x, pos.y, pos.z), " + de::toString(levelNdx) + "));\n";
1242 " ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
1243 " imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n";
1249 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1252 //! Load/store test base implementation
1253 class LoadStoreTestInstance : public BaseTestInstance
1256 LoadStoreTestInstance (Context& context,
1257 const Texture& texture,
1258 const VkFormat format,
1259 const VkFormat imageFormat,
1260 const bool declareImageFormatInShader,
1261 const bool singleLayerBind,
1262 const bool minalign,
1263 const bool bufferLoadUniform);
1266 virtual Buffer* getResultBuffer (void) const = 0; //!< Get the buffer that contains the result image
1268 tcu::TestStatus verifyResult (void);
1270 // Add empty implementations for functions that might be not needed
1271 void commandBeforeCompute (const VkCommandBuffer) {}
1272 void commandBetweenShaderInvocations (const VkCommandBuffer) {}
1273 void commandAfterCompute (const VkCommandBuffer) {}
1275 de::MovePtr<Buffer> m_imageBuffer; //!< Source data and helper buffer
1276 const VkDeviceSize m_imageSizeBytes;
1277 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
1278 tcu::TextureLevel m_referenceImage; //!< Used as input data and later to verify result image
1280 bool m_bufferLoadUniform;
1281 VkDescriptorType m_bufferLoadDescriptorType;
1282 VkBufferUsageFlagBits m_bufferLoadUsageBit;
1285 LoadStoreTestInstance::LoadStoreTestInstance (Context& context,
1286 const Texture& texture,
1287 const VkFormat format,
1288 const VkFormat imageFormat,
1289 const bool declareImageFormatInShader,
1290 const bool singleLayerBind,
1291 const bool minalign,
1292 const bool bufferLoadUniform)
1293 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1294 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format))
1295 , m_imageFormat (imageFormat)
1296 , m_referenceImage (generateReferenceImage(texture.size(), imageFormat, format))
1297 , m_bufferLoadUniform (bufferLoadUniform)
1299 const DeviceInterface& vk = m_context.getDeviceInterface();
1300 const VkDevice device = m_context.getDevice();
1301 Allocator& allocator = m_context.getDefaultAllocator();
1303 m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1304 m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1306 // A helper buffer with enough space to hold the whole image.
1308 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
1309 vk, device, allocator,
1310 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1311 MemoryRequirement::HostVisible));
1313 // Copy reference data to buffer for subsequent upload to image.
1315 const Allocation& alloc = m_imageBuffer->getAllocation();
1316 deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset, m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
1317 flushAlloc(vk, device, alloc);
1320 tcu::TestStatus LoadStoreTestInstance::verifyResult (void)
1322 const DeviceInterface& vk = m_context.getDeviceInterface();
1323 const VkDevice device = m_context.getDevice();
1325 // Apply the same transformation as done in the shader
1326 const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
1327 flipHorizontally(reference);
1329 const Allocation& alloc = getResultBuffer()->getAllocation();
1330 invalidateAlloc(vk, device, alloc);
1331 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), (const char *)alloc.getHostPtr() + m_dstViewOffset);
1333 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
1334 return tcu::TestStatus::pass("Passed");
1336 return tcu::TestStatus::fail("Image comparison failed");
1339 //! Load/store test for images
1340 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
1343 ImageLoadStoreTestInstance (Context& context,
1344 const Texture& texture,
1345 const VkFormat format,
1346 const VkFormat imageFormat,
1347 const bool declareImageFormatInShader,
1348 const bool singleLayerBind,
1349 const bool minalign,
1350 const bool bufferLoadUniform);
1353 VkDescriptorSetLayout prepareDescriptors (void);
1354 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
1355 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
1356 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1358 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1359 const VkPipelineLayout pipelineLayout,
1360 const int layerNdx);
1362 Buffer* getResultBuffer (void) const { return m_imageBuffer.get(); }
1364 de::MovePtr<Image> m_imageSrc;
1365 de::MovePtr<Image> m_imageDst;
1366 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1367 Move<VkDescriptorPool> m_descriptorPool;
1368 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1369 std::vector<SharedVkImageView> m_allSrcImageViews;
1370 std::vector<SharedVkImageView> m_allDstImageViews;
1373 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context& context,
1374 const Texture& texture,
1375 const VkFormat format,
1376 const VkFormat imageFormat,
1377 const bool declareImageFormatInShader,
1378 const bool singleLayerBind,
1379 const bool minalign,
1380 const bool bufferLoadUniform)
1381 : LoadStoreTestInstance (context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1382 , m_allDescriptorSets (texture.numLayers())
1383 , m_allSrcImageViews (texture.numLayers())
1384 , m_allDstImageViews (texture.numLayers())
1386 const DeviceInterface& vk = m_context.getDeviceInterface();
1387 const VkDevice device = m_context.getDevice();
1388 Allocator& allocator = m_context.getDefaultAllocator();
1389 const VkImageCreateFlags imageFlags = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1391 m_imageSrc = de::MovePtr<Image>(new Image(
1392 vk, device, allocator,
1393 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags),
1394 MemoryRequirement::Any));
1396 m_imageDst = de::MovePtr<Image>(new Image(
1397 vk, device, allocator,
1398 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags),
1399 MemoryRequirement::Any));
1402 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1404 const VkDevice device = m_context.getDevice();
1405 const DeviceInterface& vk = m_context.getDeviceInterface();
1407 const int numLayers = m_texture.numLayers();
1408 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1409 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1410 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1413 m_descriptorPool = DescriptorPoolBuilder()
1414 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1415 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1416 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1418 if (m_singleLayerBind)
1420 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1422 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1423 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1425 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1426 m_allSrcImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1427 m_allDstImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1430 else // bind all layers at once
1432 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1433 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1435 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1436 m_allSrcImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1437 m_allDstImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1440 return *m_descriptorSetLayout; // not passing the ownership
1443 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1445 const VkDevice device = m_context.getDevice();
1446 const DeviceInterface& vk = m_context.getDeviceInterface();
1448 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1449 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
1450 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
1452 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1453 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1455 DescriptorSetUpdateBuilder()
1456 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1457 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1458 .update(vk, device);
1459 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1462 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1464 const DeviceInterface& vk = m_context.getDeviceInterface();
1466 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1468 const VkImageMemoryBarrier preCopyImageBarriers[] =
1470 makeImageMemoryBarrier(
1471 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1472 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1473 m_imageSrc->get(), fullImageSubresourceRange),
1474 makeImageMemoryBarrier(
1475 0u, VK_ACCESS_SHADER_WRITE_BIT,
1476 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1477 m_imageDst->get(), fullImageSubresourceRange)
1480 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1481 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1482 m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1484 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1485 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1488 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1489 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1490 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1491 m_imageSrc->get(), fullImageSubresourceRange);
1493 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1495 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
1496 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);
1500 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1502 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1505 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1507 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1510 //! Load/store Lod AMD test for images
1511 class ImageLoadStoreLodAMDTestInstance : public BaseTestInstance
1514 ImageLoadStoreLodAMDTestInstance (Context& context,
1515 const Texture& texture,
1516 const VkFormat format,
1517 const VkFormat imageFormat,
1518 const bool declareImageFormatInShader,
1519 const bool singleLayerBind,
1520 const bool minalign,
1521 const bool bufferLoadUniform);
1524 VkDescriptorSetLayout prepareDescriptors (void);
1525 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
1526 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
1527 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1529 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1530 const VkPipelineLayout pipelineLayout,
1531 const int layerNdx);
1533 Buffer* getResultBuffer (void) const { return m_imageBuffer.get(); }
1534 tcu::TestStatus verifyResult (void);
1536 de::MovePtr<Buffer> m_imageBuffer; //!< Source data and helper buffer
1537 const VkDeviceSize m_imageSizeBytes;
1538 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
1539 std::vector<tcu::TextureLevel> m_referenceImages; //!< Used as input data and later to verify result image
1541 bool m_bufferLoadUniform;
1542 VkDescriptorType m_bufferLoadDescriptorType;
1543 VkBufferUsageFlagBits m_bufferLoadUsageBit;
1545 de::MovePtr<Image> m_imageSrc;
1546 de::MovePtr<Image> m_imageDst;
1547 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1548 Move<VkDescriptorPool> m_descriptorPool;
1549 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1550 std::vector<SharedVkImageView> m_allSrcImageViews;
1551 std::vector<SharedVkImageView> m_allDstImageViews;
1555 ImageLoadStoreLodAMDTestInstance::ImageLoadStoreLodAMDTestInstance (Context& context,
1556 const Texture& texture,
1557 const VkFormat format,
1558 const VkFormat imageFormat,
1559 const bool declareImageFormatInShader,
1560 const bool singleLayerBind,
1561 const bool minalign,
1562 const bool bufferLoadUniform)
1563 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1564 , m_imageSizeBytes (getMipmapImageTotalSizeBytes(texture, format))
1565 , m_imageFormat (imageFormat)
1566 , m_bufferLoadUniform (bufferLoadUniform)
1567 , m_allDescriptorSets (texture.numLayers())
1568 , m_allSrcImageViews (texture.numLayers())
1569 , m_allDstImageViews (texture.numLayers())
1571 const DeviceInterface& vk = m_context.getDeviceInterface();
1572 const VkDevice device = m_context.getDevice();
1573 Allocator& allocator = m_context.getDefaultAllocator();
1574 const VkImageCreateFlags imageFlags = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1576 const VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(m_texture.numSamples()); // integer and bit mask are aligned, so we can cast like this
1578 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1580 tcu::TextureLevel referenceImage = generateReferenceImage(texture.size(levelNdx), imageFormat, format);
1581 m_referenceImages.push_back(referenceImage);
1584 m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1585 m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1587 // A helper buffer with enough space to hold the whole image.
1588 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
1589 vk, device, allocator,
1590 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1591 MemoryRequirement::HostVisible));
1593 // Copy reference data to buffer for subsequent upload to image.
1595 const Allocation& alloc = m_imageBuffer->getAllocation();
1596 VkDeviceSize bufferOffset = 0u;
1597 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1599 deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset + bufferOffset, m_referenceImages[levelNdx].getAccess().getDataPtr(), static_cast<size_t>(getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx)));
1600 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1602 flushAlloc(vk, device, alloc);
1606 const VkImageCreateInfo imageParamsSrc =
1608 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1609 DE_NULL, // const void* pNext;
1610 (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags, // VkImageCreateFlags flags;
1611 mapImageType(m_texture.type()), // VkImageType imageType;
1612 m_imageFormat, // VkFormat format;
1613 makeExtent3D(m_texture.layerSize()), // VkExtent3D extent;
1614 (deUint32)m_texture.numMipmapLevels(), // deUint32 mipLevels;
1615 (deUint32)m_texture.numLayers(), // deUint32 arrayLayers;
1616 samples, // VkSampleCountFlagBits samples;
1617 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1618 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
1619 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1620 0u, // deUint32 queueFamilyIndexCount;
1621 DE_NULL, // const deUint32* pQueueFamilyIndices;
1622 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1625 m_imageSrc = de::MovePtr<Image>(new Image(
1626 vk, device, allocator,
1628 MemoryRequirement::Any));
1632 const VkImageCreateInfo imageParamsDst =
1634 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1635 DE_NULL, // const void* pNext;
1636 (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags, // VkImageCreateFlags flags;
1637 mapImageType(m_texture.type()), // VkImageType imageType;
1638 m_imageFormat, // VkFormat format;
1639 makeExtent3D(m_texture.layerSize()), // VkExtent3D extent;
1640 (deUint32)m_texture.numMipmapLevels(), // deUint32 mipLevels;
1641 (deUint32)m_texture.numLayers(), // deUint32 arrayLayers;
1642 samples, // VkSampleCountFlagBits samples;
1643 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1644 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1645 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1646 0u, // deUint32 queueFamilyIndexCount;
1647 DE_NULL, // const deUint32* pQueueFamilyIndices;
1648 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1651 m_imageDst = de::MovePtr<Image>(new Image(
1652 vk, device, allocator,
1654 MemoryRequirement::Any));
1658 tcu::TestStatus ImageLoadStoreLodAMDTestInstance::verifyResult (void)
1660 const DeviceInterface& vk = m_context.getDeviceInterface();
1661 const VkDevice device = m_context.getDevice();
1663 const Allocation& alloc = getResultBuffer()->getAllocation();
1664 invalidateAlloc(vk, device, alloc);
1666 VkDeviceSize bufferOffset = 0;
1667 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1669 // Apply the same transformation as done in the shader
1670 const tcu::PixelBufferAccess reference = m_referenceImages[levelNdx].getAccess();
1671 flipHorizontally(reference);
1673 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(levelNdx), (const char *)alloc.getHostPtr() + m_dstViewOffset + bufferOffset);
1675 if (!comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result, levelNdx))
1677 std::ostringstream errorMessage;
1678 errorMessage << "Image Level " << levelNdx << " comparison failed";
1679 return tcu::TestStatus::fail(errorMessage.str());
1681 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1684 return tcu::TestStatus::pass("Passed");
1687 VkDescriptorSetLayout ImageLoadStoreLodAMDTestInstance::prepareDescriptors (void)
1689 const VkDevice device = m_context.getDevice();
1690 const DeviceInterface& vk = m_context.getDeviceInterface();
1692 const int numLayers = m_texture.numLayers();
1693 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1694 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1695 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1698 m_descriptorPool = DescriptorPoolBuilder()
1699 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1700 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1701 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1703 if (m_singleLayerBind)
1705 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1707 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1708 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), layerNdx, 1u);
1710 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1711 m_allSrcImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1712 m_allDstImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1715 else // bind all layers at once
1717 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1718 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, numLayers);
1720 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1721 m_allSrcImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1722 m_allDstImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1725 return *m_descriptorSetLayout; // not passing the ownership
1728 void ImageLoadStoreLodAMDTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1730 const VkDevice device = m_context.getDevice();
1731 const DeviceInterface& vk = m_context.getDeviceInterface();
1733 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1734 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
1735 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
1737 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1738 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1740 DescriptorSetUpdateBuilder()
1741 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1742 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1743 .update(vk, device);
1744 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1747 void ImageLoadStoreLodAMDTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1749 const DeviceInterface& vk = m_context.getDeviceInterface();
1750 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, m_texture.numLayers());
1752 const VkImageMemoryBarrier preCopyImageBarriers[] =
1754 makeImageMemoryBarrier(
1755 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1756 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1757 m_imageSrc->get(), fullImageSubresourceRange),
1758 makeImageMemoryBarrier(
1759 0u, VK_ACCESS_SHADER_WRITE_BIT,
1760 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1761 m_imageDst->get(), fullImageSubresourceRange)
1764 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1765 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1766 m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1768 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1769 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1772 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1773 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1774 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1775 m_imageSrc->get(), fullImageSubresourceRange);
1777 std::vector<VkBufferImageCopy> copyRegions;
1778 VkDeviceSize bufferOffset = 0u;
1779 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1781 const VkBufferImageCopy copyParams =
1783 bufferOffset, // VkDeviceSize bufferOffset;
1784 0u, // deUint32 bufferRowLength;
1785 0u, // deUint32 bufferImageHeight;
1786 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, m_texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
1787 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1788 makeExtent3D(m_texture.layerSize(levelNdx)), // VkExtent3D imageExtent;
1790 copyRegions.push_back(copyParams);
1791 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1794 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32) copyRegions.size(), copyRegions.data());
1795 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);
1799 void ImageLoadStoreLodAMDTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1801 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1804 void ImageLoadStoreLodAMDTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1806 commandCopyMipmapImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageFormat, m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1809 //! Load/store test for buffers
1810 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
1813 BufferLoadStoreTestInstance (Context& context,
1814 const Texture& texture,
1815 const VkFormat format,
1816 const VkFormat imageFormat,
1817 const bool declareImageFormatInShader,
1818 const bool minalign,
1819 const bool bufferLoadUniform);
1822 VkDescriptorSetLayout prepareDescriptors (void);
1823 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1825 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1826 const VkPipelineLayout pipelineLayout,
1827 const int layerNdx);
1829 Buffer* getResultBuffer (void) const { return m_imageBufferDst.get(); }
1831 de::MovePtr<Buffer> m_imageBufferDst;
1832 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1833 Move<VkDescriptorPool> m_descriptorPool;
1834 Move<VkDescriptorSet> m_descriptorSet;
1835 Move<VkBufferView> m_bufferViewSrc;
1836 Move<VkBufferView> m_bufferViewDst;
1839 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context& context,
1840 const Texture& texture,
1841 const VkFormat format,
1842 const VkFormat imageFormat,
1843 const bool declareImageFormatInShader,
1844 const bool minalign,
1845 const bool bufferLoadUniform)
1846 : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false, minalign, bufferLoadUniform)
1848 const DeviceInterface& vk = m_context.getDeviceInterface();
1849 const VkDevice device = m_context.getDevice();
1850 Allocator& allocator = m_context.getDefaultAllocator();
1852 // Create a destination buffer.
1854 m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
1855 vk, device, allocator,
1856 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
1857 MemoryRequirement::HostVisible));
1860 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
1862 const DeviceInterface& vk = m_context.getDeviceInterface();
1863 const VkDevice device = m_context.getDevice();
1865 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1866 .addSingleBinding(m_bufferLoadDescriptorType, VK_SHADER_STAGE_COMPUTE_BIT)
1867 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1870 m_descriptorPool = DescriptorPoolBuilder()
1871 .addType(m_bufferLoadDescriptorType)
1872 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1873 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1875 VkFormat dstFormat = formatHasThreeComponents(m_format) ? getSingleComponentFormat(m_format) : m_format;
1877 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1878 m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_srcViewOffset, m_imageSizeBytes);
1879 m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), dstFormat, m_dstViewOffset, m_imageSizeBytes);
1881 return *m_descriptorSetLayout; // not passing the ownership
1884 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1886 DE_ASSERT(layerNdx == 0);
1889 const VkDevice device = m_context.getDevice();
1890 const DeviceInterface& vk = m_context.getDeviceInterface();
1892 DescriptorSetUpdateBuilder()
1893 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), m_bufferLoadDescriptorType, &m_bufferViewSrc.get())
1894 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
1895 .update(vk, device);
1896 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1899 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1901 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes + m_dstViewOffset);
1904 TestInstance* StoreTest::createInstance (Context& context) const
1906 if (m_texture.type() == IMAGE_TYPE_BUFFER)
1907 return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_minalign);
1909 return new ImageStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_singleLayerBind, m_minalign);
1912 TestInstance* LoadStoreTest::createInstance (Context& context) const
1914 if (m_imageLoadStoreLodAMD)
1915 return new ImageLoadStoreLodAMDTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
1917 if (m_texture.type() == IMAGE_TYPE_BUFFER)
1918 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_minalign, m_bufferLoadUniform);
1920 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
1923 class ImageExtendOperandTestInstance : public BaseTestInstance
1926 ImageExtendOperandTestInstance (Context& context,
1927 const Texture& texture,
1928 const VkFormat readFormat,
1929 const VkFormat writeFormat,
1930 bool relaxedPrecision);
1932 virtual ~ImageExtendOperandTestInstance (void) {}
1936 VkDescriptorSetLayout prepareDescriptors (void);
1937 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
1938 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
1939 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1941 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1942 const VkPipelineLayout pipelineLayout,
1943 const int layerNdx);
1945 tcu::TestStatus verifyResult (void);
1950 tcu::TextureLevel m_inputImageData;
1952 de::MovePtr<Image> m_imageSrc; // source image
1953 SharedVkImageView m_imageSrcView;
1954 VkDeviceSize m_imageSrcSize;
1956 de::MovePtr<Image> m_imageDst; // dest image
1957 SharedVkImageView m_imageDstView;
1958 VkFormat m_imageDstFormat;
1959 VkDeviceSize m_imageDstSize;
1961 de::MovePtr<Buffer> m_buffer; // result buffer
1963 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1964 Move<VkDescriptorPool> m_descriptorPool;
1965 SharedVkDescriptorSet m_descriptorSet;
1967 bool m_relaxedPrecision;
1970 ImageExtendOperandTestInstance::ImageExtendOperandTestInstance (Context& context,
1971 const Texture& texture,
1972 const VkFormat readFormat,
1973 const VkFormat writeFormat,
1974 bool relaxedPrecision)
1975 : BaseTestInstance (context, texture, readFormat, true, true, false, false)
1976 , m_imageDstFormat (writeFormat)
1977 , m_relaxedPrecision (relaxedPrecision)
1979 const DeviceInterface& vk = m_context.getDeviceInterface();
1980 const VkDevice device = m_context.getDevice();
1981 Allocator& allocator = m_context.getDefaultAllocator();
1982 const deInt32 width = texture.size().x();
1983 const deInt32 height = texture.size().y();
1984 const tcu::TextureFormat textureFormat = mapVkFormat(m_format);
1986 // Generate reference image
1987 m_isSigned = (getTextureChannelClass(textureFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
1988 m_inputImageData.setStorage(textureFormat, width, height, 1);
1990 const tcu::PixelBufferAccess access = m_inputImageData.getAccess();
1991 const int valueStart = (m_isSigned ? (-width / 2) : 0);
1993 for (int x = 0; x < width; ++x)
1994 for (int y = 0; y < height; ++y)
1996 const tcu::IVec4 color(valueStart + x, valueStart + y, valueStart, valueStart);
1997 access.setPixel(color, x, y);
2000 // Create source image
2001 m_imageSrc = de::MovePtr<Image>(new Image(
2002 vk, device, allocator,
2003 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0u),
2004 MemoryRequirement::Any));
2006 // Create destination image
2007 m_imageDst = de::MovePtr<Image>(new Image(
2008 vk, device, allocator,
2009 makeImageCreateInfo(m_texture, m_imageDstFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
2010 MemoryRequirement::Any));
2012 // Compute image and buffer sizes
2013 m_imageSrcSize = width * height * tcu::getPixelSize(textureFormat);
2014 m_imageDstSize = width * height * tcu::getPixelSize(mapVkFormat(m_imageDstFormat));
2015 VkDeviceSize bufferSizeBytes = de::max(m_imageSrcSize, m_imageDstSize);
2017 // Create helper buffer able to store input data and image write result
2018 m_buffer = de::MovePtr<Buffer>(new Buffer(
2019 vk, device, allocator,
2020 makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
2021 MemoryRequirement::HostVisible));
2023 const Allocation& alloc = m_buffer->getAllocation();
2024 deMemcpy(alloc.getHostPtr(), m_inputImageData.getAccess().getDataPtr(), static_cast<size_t>(m_imageSrcSize));
2025 flushAlloc(vk, device, alloc);
2028 VkDescriptorSetLayout ImageExtendOperandTestInstance::prepareDescriptors (void)
2030 const DeviceInterface& vk = m_context.getDeviceInterface();
2031 const VkDevice device = m_context.getDevice();
2033 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2034 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2035 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2038 m_descriptorPool = DescriptorPoolBuilder()
2039 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2040 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2041 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
2043 const VkImageViewType viewType = mapImageViewType(m_texture.type());
2044 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2046 m_descriptorSet = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
2047 m_imageSrcView = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
2048 m_imageDstView = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_imageDstFormat, subresourceRange));
2050 return *m_descriptorSetLayout; // not passing the ownership
2053 void ImageExtendOperandTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
2057 const DeviceInterface& vk = m_context.getDeviceInterface();
2058 const VkDevice device = m_context.getDevice();
2059 const VkDescriptorSet descriptorSet = **m_descriptorSet;
2061 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageSrcView, VK_IMAGE_LAYOUT_GENERAL);
2062 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageDstView, VK_IMAGE_LAYOUT_GENERAL);
2064 typedef DescriptorSetUpdateBuilder::Location DSUBL;
2065 DescriptorSetUpdateBuilder()
2066 .writeSingle(descriptorSet, DSUBL::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
2067 .writeSingle(descriptorSet, DSUBL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
2068 .update(vk, device);
2069 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
2072 void ImageExtendOperandTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
2074 const DeviceInterface& vk = m_context.getDeviceInterface();
2076 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
2078 const VkImageMemoryBarrier preCopyImageBarriers[] =
2080 makeImageMemoryBarrier(
2081 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
2082 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2083 m_imageSrc->get(), fullImageSubresourceRange),
2084 makeImageMemoryBarrier(
2085 0u, VK_ACCESS_SHADER_WRITE_BIT,
2086 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
2087 m_imageDst->get(), fullImageSubresourceRange)
2090 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
2091 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2092 m_buffer->get(), 0ull, m_imageSrcSize);
2094 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
2095 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
2098 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
2099 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
2100 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
2101 m_imageSrc->get(), fullImageSubresourceRange);
2103 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
2105 vk.cmdCopyBufferToImage(cmdBuffer, m_buffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
2106 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);
2110 void ImageExtendOperandTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
2112 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
2115 void ImageExtendOperandTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
2117 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_buffer->get(), m_imageDstSize, m_texture);
2120 // Clears the high bits of every pixel in the pixel buffer, leaving only the lowest 16 bits of each component.
2121 void clearHighBits (const tcu::PixelBufferAccess& pixels, int width, int height)
2123 for (int y = 0; y < height; ++y)
2124 for (int x = 0; x < width; ++x)
2126 auto color = pixels.getPixelUint(x, y);
2127 for (int c = 0; c < decltype(color)::SIZE; ++c)
2128 color[c] &= 0xFFFFull;
2129 pixels.setPixel(color, x, y);
2133 tcu::TestStatus ImageExtendOperandTestInstance::verifyResult (void)
2135 const DeviceInterface& vk = m_context.getDeviceInterface();
2136 const VkDevice device = m_context.getDevice();
2137 const tcu::IVec3 imageSize = m_texture.size();
2138 const tcu::PixelBufferAccess inputAccess = m_inputImageData.getAccess();
2139 const deInt32 width = inputAccess.getWidth();
2140 const deInt32 height = inputAccess.getHeight();
2141 tcu::TextureLevel refImage (mapVkFormat(m_imageDstFormat), width, height);
2142 tcu::PixelBufferAccess refAccess = refImage.getAccess();
2144 for (int x = 0; x < width; ++x)
2145 for (int y = 0; y < height; ++y)
2147 tcu::IVec4 color = inputAccess.getPixelInt(x, y);
2148 refAccess.setPixel(color, x, y);
2151 const Allocation& alloc = m_buffer->getAllocation();
2152 invalidateAlloc(vk, device, alloc);
2153 const tcu::PixelBufferAccess result(mapVkFormat(m_imageDstFormat), imageSize, alloc.getHostPtr());
2155 if (m_relaxedPrecision)
2157 // Preserve the lowest 16 bits of the reference and result pixels only.
2158 clearHighBits(refAccess, width, height);
2159 clearHighBits(result, width, height);
2162 if (tcu::intThresholdCompare (m_context.getTestContext().getLog(), "Comparison", "Comparison", refAccess, result, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT, true/*use64Bits*/))
2163 return tcu::TestStatus::pass("Passed");
2165 return tcu::TestStatus::fail("Image comparison failed");
2168 enum class ExtendTestType
2175 enum class ExtendOperand
2181 class ImageExtendOperandTest : public TestCase
2184 ImageExtendOperandTest (tcu::TestContext& testCtx,
2185 const std::string& name,
2186 const Texture texture,
2187 const VkFormat readFormat,
2188 const VkFormat writeFormat,
2189 const bool signedInt,
2190 const bool relaxedPrecision,
2191 ExtendTestType extendTestType);
2193 void checkSupport (Context& context) const;
2194 void initPrograms (SourceCollections& programCollection) const;
2195 TestInstance* createInstance (Context& context) const;
2198 bool isWriteTest () const { return (m_extendTestType == ExtendTestType::WRITE) ||
2199 (m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL); }
2201 const Texture m_texture;
2202 VkFormat m_readFormat;
2203 VkFormat m_writeFormat;
2204 bool m_operandForce; // Use an operand that doesn't match SampledType?
2205 bool m_relaxedPrecision;
2206 ExtendTestType m_extendTestType;
2209 ImageExtendOperandTest::ImageExtendOperandTest (tcu::TestContext& testCtx,
2210 const std::string& name,
2211 const Texture texture,
2212 const VkFormat readFormat,
2213 const VkFormat writeFormat,
2214 const bool operandForce,
2215 const bool relaxedPrecision,
2216 ExtendTestType extendTestType)
2217 : TestCase (testCtx, name, "")
2218 , m_texture (texture)
2219 , m_readFormat (readFormat)
2220 , m_writeFormat (writeFormat)
2221 , m_operandForce (operandForce)
2222 , m_relaxedPrecision (relaxedPrecision)
2223 , m_extendTestType (extendTestType)
2227 void checkFormatProperties (Context& context, VkFormat format)
2229 const VkFormatProperties3 formatProperties (context.getFormatProperties(format));
2231 if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2232 TCU_THROW(NotSupportedError, "Format not supported for storage images");
2235 void check64BitSupportIfNeeded (Context& context, VkFormat readFormat, VkFormat writeFormat)
2237 if (is64BitIntegerFormat(readFormat) || is64BitIntegerFormat(writeFormat))
2239 const auto& features = context.getDeviceFeatures();
2240 if (!features.shaderInt64)
2241 TCU_THROW(NotSupportedError, "64-bit integers not supported in shaders");
2245 void ImageExtendOperandTest::checkSupport (Context& context) const
2247 if (!context.requireDeviceFunctionality("VK_KHR_spirv_1_4"))
2248 TCU_THROW(NotSupportedError, "VK_KHR_spirv_1_4 not supported");
2250 if ((m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL) &&
2251 (context.getUsedApiVersion() < VK_API_VERSION_1_3))
2252 TCU_THROW(NotSupportedError, "Vulkan 1.3 or higher is required for this test to run");
2254 check64BitSupportIfNeeded(context, m_readFormat, m_writeFormat);
2256 checkFormatProperties(context, m_readFormat);
2257 checkFormatProperties(context, m_writeFormat);
2260 void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection) const
2262 tcu::StringTemplate shaderTemplate(
2263 "OpCapability Shader\n"
2264 "OpCapability StorageImageExtendedFormats\n"
2269 "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
2270 "OpMemoryModel Logical GLSL450\n"
2271 "OpEntryPoint GLCompute %main \"main\" %id %src_image_ptr %dst_image_ptr\n"
2272 "OpExecutionMode %main LocalSize 1 1 1\n"
2275 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2277 "OpDecorate %src_image_ptr DescriptorSet 0\n"
2278 "OpDecorate %src_image_ptr Binding 0\n"
2279 "OpDecorate %src_image_ptr NonWritable\n"
2281 "${relaxed_precision}"
2283 "OpDecorate %dst_image_ptr DescriptorSet 0\n"
2284 "OpDecorate %dst_image_ptr Binding 1\n"
2285 "OpDecorate %dst_image_ptr NonReadable\n"
2288 "%type_void = OpTypeVoid\n"
2289 "%type_i32 = OpTypeInt 32 1\n"
2290 "%type_u32 = OpTypeInt 32 0\n"
2291 "%type_vec2_i32 = OpTypeVector %type_i32 2\n"
2292 "%type_vec2_u32 = OpTypeVector %type_u32 2\n"
2293 "%type_vec3_i32 = OpTypeVector %type_i32 3\n"
2294 "%type_vec3_u32 = OpTypeVector %type_u32 3\n"
2295 "%type_vec4_i32 = OpTypeVector %type_i32 4\n"
2296 "%type_vec4_u32 = OpTypeVector %type_u32 4\n"
2299 "%type_fun_void = OpTypeFunction %type_void\n"
2303 "%type_ptr_in_vec3_u32 = OpTypePointer Input %type_vec3_u32\n"
2304 "%type_ptr_in_u32 = OpTypePointer Input %type_u32\n"
2309 "%id = OpVariable %type_ptr_in_vec3_u32 Input\n"
2311 "${image_variables}"
2314 "%main = OpFunction %type_void None %type_fun_void\n"
2315 "%label = OpLabel\n"
2319 "%idvec = OpLoad %type_vec3_u32 %id\n"
2320 "%id_xy = OpVectorShuffle %type_vec2_u32 %idvec %idvec 0 1\n"
2321 "%coord = OpBitcast %type_vec2_i32 %id_xy\n"
2322 "%value = OpImageRead ${sampled_type_vec4} %src_image %coord ${read_extend_operand}\n"
2323 " OpImageWrite %dst_image %coord %value ${write_extend_operand}\n"
2325 " OpFunctionEnd\n");
2327 const auto testedFormat = mapVkFormat(isWriteTest() ? m_writeFormat : m_readFormat);
2328 const bool isSigned = (getTextureChannelClass(testedFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2330 const auto isRead64 = is64BitIntegerFormat(m_readFormat);
2331 const auto isWrite64 = is64BitIntegerFormat(m_writeFormat);
2332 DE_ASSERT(isRead64 == isWrite64);
2334 const bool using64Bits = (isRead64 || isWrite64);
2336 // Additional capabilities when needed.
2337 std::string capability;
2338 std::string extension;
2339 std::string extraTypes;
2343 extension += "OpExtension \"SPV_EXT_shader_image_int64\"\n";
2345 "OpCapability Int64\n"
2346 "OpCapability Int64ImageEXT\n"
2349 "%type_i64 = OpTypeInt 64 1\n"
2350 "%type_u64 = OpTypeInt 64 0\n"
2351 "%type_vec3_i64 = OpTypeVector %type_i64 3\n"
2352 "%type_vec3_u64 = OpTypeVector %type_u64 3\n"
2353 "%type_vec4_i64 = OpTypeVector %type_i64 4\n"
2354 "%type_vec4_u64 = OpTypeVector %type_u64 4\n"
2358 std::string relaxed = "";
2359 if (m_relaxedPrecision)
2360 relaxed += "OpDecorate %src_image_ptr RelaxedPrecision\n";
2362 // Sampled type depends on the format sign and mismatch force flag.
2363 const bool signedSampleType = ((isSigned && !m_operandForce) || (!isSigned && m_operandForce));
2364 const std::string bits = (using64Bits ? "64" : "32");
2365 const std::string sampledTypePostfix = (signedSampleType ? "i" : "u") + bits;
2366 const std::string extendOperandStr = (isSigned ? "SignExtend" : "ZeroExtend");
2368 std::map<std::string, std::string> specializations
2370 { "image_type_id", "%type_image" },
2371 { "image_uni_ptr_type_id", "%type_ptr_uniform_const_image" },
2372 { "image_var_id", "%src_image_ptr" },
2373 { "image_id", "%src_image" },
2374 { "capability", capability },
2375 { "extension", extension },
2376 { "extra_types", extraTypes },
2377 { "relaxed_precision", relaxed },
2378 { "image_format", getSpirvFormat(m_readFormat) },
2379 { "sampled_type", (std::string("%type_") + sampledTypePostfix) },
2380 { "sampled_type_vec4", (std::string("%type_vec4_") + sampledTypePostfix) },
2381 { "read_extend_operand", (!isWriteTest() ? extendOperandStr : "") },
2382 { "write_extend_operand", (isWriteTest() ? extendOperandStr : "") },
2385 SpirvVersion spirvVersion = SPIRV_VERSION_1_4;
2386 bool allowSpirv14 = true;
2387 if (m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL)
2389 spirvVersion = SPIRV_VERSION_1_6;
2390 allowSpirv14 = false;
2391 specializations["write_extend_operand"] = "Nontemporal";
2394 // Addidtional parametrization is needed for a case when source and destination textures have same format
2395 tcu::StringTemplate imageTypeTemplate(
2396 "${image_type_id} = OpTypeImage ${sampled_type} 2D 0 0 0 2 ${image_format}\n");
2397 tcu::StringTemplate imageUniformTypeTemplate(
2398 "${image_uni_ptr_type_id} = OpTypePointer UniformConstant ${image_type_id}\n");
2399 tcu::StringTemplate imageVariablesTemplate(
2400 "${image_var_id} = OpVariable ${image_uni_ptr_type_id} UniformConstant\n");
2401 tcu::StringTemplate imageLoadTemplate(
2402 "${image_id} = OpLoad ${image_type_id} ${image_var_id}\n");
2404 std::string imageTypes;
2405 std::string imageUniformTypes;
2406 std::string imageVariables;
2407 std::string imageLoad;
2409 // If input image format is the same as output there is less spir-v definitions
2410 if (m_readFormat == m_writeFormat)
2412 imageTypes = imageTypeTemplate.specialize(specializations);
2413 imageUniformTypes = imageUniformTypeTemplate.specialize(specializations);
2414 imageVariables = imageVariablesTemplate.specialize(specializations);
2415 imageLoad = imageLoadTemplate.specialize(specializations);
2417 specializations["image_var_id"] = "%dst_image_ptr";
2418 specializations["image_id"] = "%dst_image";
2419 imageVariables += imageVariablesTemplate.specialize(specializations);
2420 imageLoad += imageLoadTemplate.specialize(specializations);
2424 specializations["image_type_id"] = "%type_src_image";
2425 specializations["image_uni_ptr_type_id"] = "%type_ptr_uniform_const_src_image";
2426 imageTypes = imageTypeTemplate.specialize(specializations);
2427 imageUniformTypes = imageUniformTypeTemplate.specialize(specializations);
2428 imageVariables = imageVariablesTemplate.specialize(specializations);
2429 imageLoad = imageLoadTemplate.specialize(specializations);
2431 specializations["image_format"] = getSpirvFormat(m_writeFormat);
2432 specializations["image_type_id"] = "%type_dst_image";
2433 specializations["image_uni_ptr_type_id"] = "%type_ptr_uniform_const_dst_image";
2434 specializations["image_var_id"] = "%dst_image_ptr";
2435 specializations["image_id"] = "%dst_image";
2436 imageTypes += imageTypeTemplate.specialize(specializations);
2437 imageUniformTypes += imageUniformTypeTemplate.specialize(specializations);
2438 imageVariables += imageVariablesTemplate.specialize(specializations);
2439 imageLoad += imageLoadTemplate.specialize(specializations);
2442 specializations["image_types"] = imageTypes;
2443 specializations["image_uniforms"] = imageUniformTypes;
2444 specializations["image_variables"] = imageVariables;
2445 specializations["image_load"] = imageLoad;
2447 // Specialize whole shader and add it to program collection
2448 programCollection.spirvAsmSources.add("comp") << shaderTemplate.specialize(specializations)
2449 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, spirvVersion, allowSpirv14);
2452 TestInstance* ImageExtendOperandTest::createInstance(Context& context) const
2454 return new ImageExtendOperandTestInstance(context, m_texture, m_readFormat, m_writeFormat, m_relaxedPrecision);
2457 static const Texture s_textures[] =
2459 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1),
2460 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8),
2461 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1),
2462 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8),
2463 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1),
2464 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6),
2465 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2*6),
2466 Texture(IMAGE_TYPE_BUFFER, tcu::IVec3(64, 1, 1), 1),
2469 const Texture& getTestTexture (const ImageType imageType)
2471 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2472 if (s_textures[textureNdx].type() == imageType)
2473 return s_textures[textureNdx];
2475 DE_FATAL("Internal error");
2476 return s_textures[0];
2479 static const VkFormat s_formats[] =
2481 VK_FORMAT_R32G32B32A32_SFLOAT,
2482 VK_FORMAT_R16G16B16A16_SFLOAT,
2483 VK_FORMAT_R32_SFLOAT,
2485 VK_FORMAT_R32G32B32A32_UINT,
2486 VK_FORMAT_R16G16B16A16_UINT,
2487 VK_FORMAT_R8G8B8A8_UINT,
2490 VK_FORMAT_R32G32B32A32_SINT,
2491 VK_FORMAT_R16G16B16A16_SINT,
2492 VK_FORMAT_R8G8B8A8_SINT,
2495 VK_FORMAT_R8G8B8A8_UNORM,
2497 VK_FORMAT_B8G8R8A8_UNORM,
2498 VK_FORMAT_B8G8R8A8_UINT,
2500 VK_FORMAT_R8G8B8A8_SNORM,
2502 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2504 VK_FORMAT_R32G32_SFLOAT,
2505 VK_FORMAT_R16G16_SFLOAT,
2506 VK_FORMAT_R16_SFLOAT,
2508 VK_FORMAT_A2B10G10R10_UINT_PACK32,
2509 VK_FORMAT_R32G32_UINT,
2510 VK_FORMAT_R16G16_UINT,
2512 VK_FORMAT_R8G8_UINT,
2515 VK_FORMAT_R32G32_SINT,
2516 VK_FORMAT_R16G16_SINT,
2518 VK_FORMAT_R8G8_SINT,
2521 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2522 VK_FORMAT_R16G16B16A16_UNORM,
2523 VK_FORMAT_R16G16B16A16_SNORM,
2524 VK_FORMAT_R16G16_UNORM,
2525 VK_FORMAT_R16_UNORM,
2526 VK_FORMAT_R8G8_UNORM,
2529 VK_FORMAT_R16G16_SNORM,
2530 VK_FORMAT_R16_SNORM,
2531 VK_FORMAT_R8G8_SNORM,
2535 static const VkFormat s_formatsThreeComponent[] =
2537 VK_FORMAT_R8G8B8_UINT,
2538 VK_FORMAT_R8G8B8_SINT,
2539 VK_FORMAT_R8G8B8_UNORM,
2540 VK_FORMAT_R8G8B8_SNORM,
2541 VK_FORMAT_R16G16B16_UINT,
2542 VK_FORMAT_R16G16B16_SINT,
2543 VK_FORMAT_R16G16B16_UNORM,
2544 VK_FORMAT_R16G16B16_SNORM,
2545 VK_FORMAT_R16G16B16_SFLOAT,
2546 VK_FORMAT_R32G32B32_UINT,
2547 VK_FORMAT_R32G32B32_SINT,
2548 VK_FORMAT_R32G32B32_SFLOAT,
2553 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
2555 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
2556 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images"));
2557 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images"));
2559 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2561 const Texture& texture = s_textures[textureNdx];
2562 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2563 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2564 const bool isLayered = (texture.numLayers() > 1);
2566 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2568 const bool hasSpirvFmt = hasSpirvFormat(s_formats[formatNdx]);
2571 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
2572 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0));
2574 if (isLayered && hasSpirvFmt)
2575 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2576 texture, s_formats[formatNdx],
2577 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2579 if (texture.type() == IMAGE_TYPE_BUFFER)
2582 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2583 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN));
2587 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2588 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2591 testGroup->addChild(testGroupWithFormat.release());
2592 testGroup->addChild(testGroupWithoutFormat.release());
2594 return testGroup.release();
2597 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
2599 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
2600 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2601 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2603 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2605 const Texture& texture = s_textures[textureNdx];
2606 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2607 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2608 const bool isLayered = (texture.numLayers() > 1);
2610 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2612 // These tests always require a SPIR-V format for the write image, even if the read
2613 // image is being used without a format.
2614 if (!hasSpirvFormat(s_formats[formatNdx]))
2617 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx]));
2618 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0));
2621 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2622 texture, s_formats[formatNdx], s_formats[formatNdx],
2623 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2624 if (texture.type() == IMAGE_TYPE_BUFFER)
2626 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));
2627 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));
2628 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN));
2629 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));
2633 if (texture.type() == IMAGE_TYPE_BUFFER)
2635 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formatsThreeComponent); ++formatNdx)
2637 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formatsThreeComponent[formatNdx]) + "_uniform", "", texture, s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2638 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));
2642 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2643 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2646 testGroup->addChild(testGroupWithFormat.release());
2647 testGroup->addChild(testGroupWithoutFormat.release());
2649 return testGroup.release();
2652 tcu::TestCaseGroup* createImageLoadStoreLodAMDTests (tcu::TestContext& testCtx)
2654 static const Texture textures[] =
2656 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8, 1, 6),
2657 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1, 1, 6),
2658 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1, 1, 6),
2659 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8, 1, 6),
2660 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1, 1, 6),
2661 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6, 1, 6),
2662 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2*6, 1, 6),
2665 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_lod", "Cases with imageLoad() followed by imageStore()"));
2666 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2667 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2669 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(textures); ++textureNdx)
2671 const Texture& texture = textures[textureNdx];
2672 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2673 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2674 const bool isLayered = (texture.numLayers() > 1);
2676 if (texture.type() == IMAGE_TYPE_BUFFER)
2679 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2681 // These tests always require a SPIR-V format for the write image, even if the read
2682 // image is being used without a format.
2683 if (!hasSpirvFormat(s_formats[formatNdx]))
2686 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));
2687 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0, DE_TRUE));
2690 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2691 texture, s_formats[formatNdx], s_formats[formatNdx],
2692 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER, DE_TRUE));
2695 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2696 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2699 testGroup->addChild(testGroupWithFormat.release());
2700 testGroup->addChild(testGroupWithoutFormat.release());
2702 return testGroup.release();
2705 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
2707 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats"));
2709 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2711 const Texture& texture = s_textures[textureNdx];
2712 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2714 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
2715 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2717 if (!hasSpirvFormat(s_formats[formatNdx]))
2720 const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
2721 if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
2722 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
2724 testGroup->addChild(groupByImageViewType.release());
2727 return testGroup.release();
2730 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
2732 const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
2733 const Texture& texture = getTestTexture(imageType);
2734 return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2740 bool relaxedOK(VkFormat format)
2742 tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(format));
2743 int maxBitDepth = deMax32(deMax32(bitDepth[0], bitDepth[1]), deMax32(bitDepth[2], bitDepth[3]));
2744 return maxBitDepth <= 16;
2747 // Get a format used for reading or writing in extension operand tests. These formats allow representing the shader sampled type to
2748 // verify results from read or write operations.
2749 VkFormat getShaderExtensionOperandFormat (bool isSigned, bool is64Bit)
2751 const VkFormat formats[] =
2753 VK_FORMAT_R32G32B32A32_UINT,
2754 VK_FORMAT_R32G32B32A32_SINT,
2758 return formats[2u * (is64Bit ? 1u : 0u) + (isSigned ? 1u : 0u)];
2761 // INT or UINT format?
2762 bool isIntegralFormat (VkFormat format)
2764 return (isIntFormat(format) || isUintFormat(format));
2767 // Return the list of formats used for the extension operand tests (SignExten/ZeroExtend).
2768 std::vector<VkFormat> getExtensionOperandFormatList (void)
2770 std::vector<VkFormat> formatList;
2772 for (auto format : s_formats)
2774 if (isIntegralFormat(format))
2775 formatList.push_back(format);
2778 formatList.push_back(VK_FORMAT_R64_SINT);
2779 formatList.push_back(VK_FORMAT_R64_UINT);
2786 tcu::TestCaseGroup* createImageExtendOperandsTests(tcu::TestContext& testCtx)
2788 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
2790 GroupPtr testGroup(new tcu::TestCaseGroup(testCtx, "extend_operands_spirv1p4", "Cases with SignExtend and ZeroExtend"));
2794 ExtendTestType testType;
2798 { ExtendTestType::READ, "read" },
2799 { ExtendTestType::WRITE, "write" },
2802 const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
2803 const auto formatList = getExtensionOperandFormatList();
2805 for (const auto format : formatList)
2807 const auto isInt = isIntFormat(format);
2808 const auto isUint = isUintFormat(format);
2809 const auto use64Bits = is64BitIntegerFormat(format);
2811 DE_ASSERT(isInt || isUint);
2813 GroupPtr formatGroup (new tcu::TestCaseGroup(testCtx, getFormatShortString(format).c_str(), ""));
2815 for (const auto& testType : testTypes)
2817 GroupPtr testTypeGroup (new tcu::TestCaseGroup(testCtx, testType.name, ""));
2819 for (int match = 0; match < 2; ++match)
2821 const bool mismatched = (match == 1);
2822 const char* matchGroupName = (mismatched ? "mismatched_sign" : "matched_sign");
2824 // SPIR-V does not allow this kind of sampled type override.
2825 if (mismatched && isUint)
2828 GroupPtr matchGroup (new tcu::TestCaseGroup(testCtx, matchGroupName, ""));
2830 for (int prec = 0; prec < 2; prec++)
2832 const bool relaxedPrecision = (prec != 0);
2834 const char* precisionName = (relaxedPrecision ? "relaxed_precision" : "normal_precision");
2835 const auto signedOther = ((isInt && !mismatched) || (isUint && mismatched));
2836 const auto otherFormat = getShaderExtensionOperandFormat(signedOther, use64Bits);
2837 const auto readFormat = (testType.testType == ExtendTestType::READ ? format : otherFormat);
2838 const auto writeFormat = (testType.testType == ExtendTestType::WRITE ? format : otherFormat);
2840 if (relaxedPrecision && !relaxedOK(readFormat))
2843 if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
2846 matchGroup->addChild(new ImageExtendOperandTest(testCtx, precisionName, texture, readFormat, writeFormat, mismatched, relaxedPrecision, testType.testType));
2849 testTypeGroup->addChild(matchGroup.release());
2852 formatGroup->addChild(testTypeGroup.release());
2855 testGroup->addChild(formatGroup.release());
2858 return testGroup.release();
2861 tcu::TestCaseGroup* createImageNontemporalOperandTests(tcu::TestContext& testCtx)
2863 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "nontemporal_operand", "Cases with Nontemporal image operand for SPOIR-V 1.6"));
2865 const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
2867 // using just integer formats for tests so that ImageExtendOperandTest could be reused
2868 const auto formatList = getExtensionOperandFormatList();
2870 for (const auto format : formatList)
2872 const std::string caseName = getFormatShortString(format);
2873 const auto readFormat = format;
2874 const auto writeFormat = getShaderExtensionOperandFormat(isIntFormat(format), is64BitIntegerFormat(format));
2876 if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
2879 // note: just testing OpImageWrite as OpImageRead is tested with addComputeImageSamplerTest
2880 testGroup->addChild(new ImageExtendOperandTest(testCtx, caseName, texture,
2881 readFormat, writeFormat, false, false, ExtendTestType::WRITE_NONTEMPORAL));
2884 return testGroup.release();