1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Image load/store Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktImageLoadStoreTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageLoadStoreUtil.hpp"
29 #include "vktImageTexture.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkImageUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43
44 #include "deMath.h"
45 #include "deUniquePtr.hpp"
46 #include "deSharedPtr.hpp"
47 #include "deStringUtil.hpp"
48
49 #include "tcuImageCompare.hpp"
50 #include "tcuTexture.hpp"
51 #include "tcuTextureUtil.hpp"
52 #include "tcuFloat.hpp"
53 #include "tcuStringTemplate.hpp"
54
55 #include <string>
56 #include <vector>
57 #include <map>
58
59 using namespace vk;
60
61 namespace vkt
62 {
63 namespace image
64 {
65 namespace
66 {
67
68 // Check for three-component (non-packed) format, i.e. pixel size is a multiple of 3.
formatHasThreeComponents(VkFormat format)69 bool formatHasThreeComponents(VkFormat format)
70 {
71 const tcu::TextureFormat texFormat = mapVkFormat(format);
72 return (getPixelSize(texFormat) % 3) == 0;
73 }
74
getSingleComponentFormat(VkFormat format)75 VkFormat getSingleComponentFormat(VkFormat format)
76 {
77 tcu::TextureFormat texFormat = mapVkFormat(format);
78 texFormat = tcu::TextureFormat(tcu::TextureFormat::R, texFormat.type);
79 return mapTextureFormat(texFormat);
80 }
81
makeBufferImageCopy(const Texture & texture)82 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
83 {
84 return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
85 }
86
getLayerOrSlice(const Texture & texture,const tcu::ConstPixelBufferAccess access,const int layer)87 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
88 {
89 switch (texture.type())
90 {
91 case IMAGE_TYPE_1D:
92 case IMAGE_TYPE_2D:
93 case IMAGE_TYPE_BUFFER:
94 // Not layered
95 DE_ASSERT(layer == 0);
96 return access;
97
98 case IMAGE_TYPE_1D_ARRAY:
99 return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
100
101 case IMAGE_TYPE_2D_ARRAY:
102 case IMAGE_TYPE_CUBE:
103 case IMAGE_TYPE_CUBE_ARRAY:
104 case IMAGE_TYPE_3D: // 3d texture is treated as if depth was the layers
105 return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
106
107 default:
108 DE_FATAL("Internal test error");
109 return tcu::ConstPixelBufferAccess();
110 }
111 }
112
113 //! \return the size in bytes of a given level of a mipmap image, including array layers.
getMipmapLevelImageSizeBytes(const Texture & texture,const vk::VkFormat format,const deUint32 mipmapLevel)114 vk::VkDeviceSize getMipmapLevelImageSizeBytes (const Texture& texture, const vk::VkFormat format, const deUint32 mipmapLevel)
115 {
116 tcu::IVec3 size = texture.size(mipmapLevel);
117 return tcu::getPixelSize(vk::mapVkFormat(format)) * size.x() * size.y() * size.z();
118 }
119
120 //! \return the size in bytes of the whole mipmap image, including all mipmap levels and array layers
getMipmapImageTotalSizeBytes(const Texture & texture,const vk::VkFormat format)121 vk::VkDeviceSize getMipmapImageTotalSizeBytes (const Texture& texture, const vk::VkFormat format)
122 {
123 vk::VkDeviceSize size = 0u;
124 deInt32 levelCount = 0u;
125
126 do
127 {
128 size += getMipmapLevelImageSizeBytes(texture, format, levelCount);
129 levelCount++;
130 } while (levelCount < texture.numMipmapLevels());
131 return size;
132 }
133
134 //! \return true if all layers match in both pixel buffers
comparePixelBuffers(tcu::TestLog & log,const Texture & texture,const VkFormat format,const tcu::ConstPixelBufferAccess reference,const tcu::ConstPixelBufferAccess result,const deUint32 mipmapLevel=0u)135 bool comparePixelBuffers (tcu::TestLog& log,
136 const Texture& texture,
137 const VkFormat format,
138 const tcu::ConstPixelBufferAccess reference,
139 const tcu::ConstPixelBufferAccess result,
140 const deUint32 mipmapLevel = 0u)
141 {
142 DE_ASSERT(reference.getFormat() == result.getFormat());
143 DE_ASSERT(reference.getSize() == result.getSize());
144
145 const bool is3d = (texture.type() == IMAGE_TYPE_3D);
146 const int numLayersOrSlices = (is3d ? texture.size(mipmapLevel).z() : texture.numLayers());
147 const int numCubeFaces = 6;
148
149 int passedLayers = 0;
150 for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
151 {
152 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
153 const std::string comparisonDesc = "Image Comparison, " +
154 (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
155 is3d ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx) + " , level " + de::toString(mipmapLevel));
156
157 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
158 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
159
160 bool ok = false;
161
162 switch (tcu::getTextureChannelClass(mapVkFormat(format).type))
163 {
164 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
165 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
166 {
167 ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
168 break;
169 }
170
171 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
172 {
173 // Allow error of minimum representable difference
174 const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()) - 1u).cast<float>());
175
176 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
177 break;
178 }
179
180 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
181 {
182 // Allow error of minimum representable difference
183 const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << (tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u)) - 1u).cast<float>());
184
185 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
186 break;
187 }
188
189 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
190 {
191 // Convert target format ulps to float ulps and allow 1 ulp difference
192 const tcu::UVec4 threshold (tcu::UVec4(1u) << (tcu::UVec4(23) - tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()));
193
194 ok = tcu::floatUlpThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
195 break;
196 }
197
198 default:
199 DE_FATAL("Unknown channel class");
200 }
201
202 if (ok)
203 ++passedLayers;
204 }
205
206 return passedLayers == numLayersOrSlices;
207 }
208
209 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
replaceBadFloatReinterpretValues(const tcu::PixelBufferAccess access)210 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
211 {
212 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
213
214 for (int z = 0; z < access.getDepth(); ++z)
215 for (int y = 0; y < access.getHeight(); ++y)
216 for (int x = 0; x < access.getWidth(); ++x)
217 {
218 const tcu::Vec4 color(access.getPixel(x, y, z));
219 tcu::Vec4 newColor = color;
220
221 for (int i = 0; i < 4; ++i)
222 {
223 if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
224 {
225 const tcu::Float16 f(color[i]);
226 if (f.isDenorm() || f.isInf() || f.isNaN())
227 newColor[i] = 0.0f;
228 }
229 else
230 {
231 const tcu::Float32 f(color[i]);
232 if (f.isDenorm() || f.isInf() || f.isNaN())
233 newColor[i] = 0.0f;
234 }
235 }
236
237 if (newColor != color)
238 access.setPixel(newColor, x, y, z);
239 }
240 }
241
242 //!< replace invalid pixels in the image (-128)
replaceSnormReinterpretValues(const tcu::PixelBufferAccess access)243 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
244 {
245 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
246
247 for (int z = 0; z < access.getDepth(); ++z)
248 for (int y = 0; y < access.getHeight(); ++y)
249 for (int x = 0; x < access.getWidth(); ++x)
250 {
251 const tcu::IVec4 color(access.getPixelInt(x, y, z));
252 tcu::IVec4 newColor = color;
253
254 for (int i = 0; i < 4; ++i)
255 {
256 const deInt32 oldColor(color[i]);
257 if (oldColor == -128) newColor[i] = -127;
258 }
259
260 if (newColor != color)
261 access.setPixel(newColor, x, y, z);
262 }
263 }
264
generateReferenceImage(const tcu::IVec3 & imageSize,const VkFormat imageFormat,const VkFormat readFormat)265 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat)
266 {
267 // Generate a reference image data using the storage format
268
269 tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
270 const tcu::PixelBufferAccess access = reference.getAccess();
271
272 const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
273 const float storeColorBias = computeStoreColorBias(imageFormat);
274
275 const bool intFormat = isIntegerFormat(imageFormat);
276 const bool storeNegativeValues = isSignedFormat(imageFormat) && (storeColorBias == 0);
277 const int xMax = imageSize.x() - 1;
278 const int yMax = imageSize.y() - 1;
279
280 for (int z = 0; z < imageSize.z(); ++z)
281 for (int y = 0; y < imageSize.y(); ++y)
282 for (int x = 0; x < imageSize.x(); ++x)
283 {
284 tcu::IVec4 color(x^y^z, (xMax - x)^y^z, x^(yMax - y)^z, (xMax - x)^(yMax - y)^z);
285
286 if (storeNegativeValues)
287 color -= tcu::IVec4(deRoundFloatToInt32((float)de::max(xMax, yMax) / 2.0f));
288
289 if (intFormat)
290 access.setPixel(color, x, y, z);
291 else
292 access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z);
293 }
294
295 // If the image is to be accessed as a float texture, get rid of invalid values
296
297 if (isFloatFormat(readFormat) && imageFormat != readFormat)
298 replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
299 if (isSnormFormat(readFormat) && imageFormat != readFormat)
300 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
301
302 return reference;
303 }
304
generateReferenceImage(const tcu::IVec3 & imageSize,const VkFormat imageFormat)305 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat)
306 {
307 return generateReferenceImage(imageSize, imageFormat, imageFormat);
308 }
309
flipHorizontally(const tcu::PixelBufferAccess access)310 void flipHorizontally (const tcu::PixelBufferAccess access)
311 {
312 const int xMax = access.getWidth() - 1;
313 const int halfWidth = access.getWidth() / 2;
314
315 if (isIntegerFormat(mapTextureFormat(access.getFormat())))
316 for (int z = 0; z < access.getDepth(); z++)
317 for (int y = 0; y < access.getHeight(); y++)
318 for (int x = 0; x < halfWidth; x++)
319 {
320 const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
321 access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
322 access.setPixel(temp, x, y, z);
323 }
324 else
325 for (int z = 0; z < access.getDepth(); z++)
326 for (int y = 0; y < access.getHeight(); y++)
327 for (int x = 0; x < halfWidth; x++)
328 {
329 const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
330 access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
331 access.setPixel(temp, x, y, z);
332 }
333 }
334
formatsAreCompatible(const VkFormat format0,const VkFormat format1)335 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
336 {
337 return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
338 }
339
commandImageWriteBarrierBetweenShaderInvocations(Context & context,const VkCommandBuffer cmdBuffer,const VkImage image,const Texture & texture)340 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
341 {
342 const DeviceInterface& vk = context.getDeviceInterface();
343
344 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
345 const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
346 VK_ACCESS_SHADER_WRITE_BIT, 0u,
347 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
348 image, fullImageSubresourceRange);
349
350 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);
351 }
352
commandBufferWriteBarrierBeforeHostRead(Context & context,const VkCommandBuffer cmdBuffer,const VkBuffer buffer,const VkDeviceSize bufferSizeBytes)353 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
354 {
355 const DeviceInterface& vk = context.getDeviceInterface();
356
357 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
358 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
359 buffer, 0ull, bufferSizeBytes);
360
361 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);
362 }
363
364 //! Copy all layers of an image to a buffer.
commandCopyImageToBuffer(Context & context,const VkCommandBuffer cmdBuffer,const VkImage image,const VkBuffer buffer,const VkDeviceSize bufferSizeBytes,const Texture & texture)365 void commandCopyImageToBuffer (Context& context,
366 const VkCommandBuffer cmdBuffer,
367 const VkImage image,
368 const VkBuffer buffer,
369 const VkDeviceSize bufferSizeBytes,
370 const Texture& texture)
371 {
372 const DeviceInterface& vk = context.getDeviceInterface();
373
374 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
375 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
376 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
377 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
378 image, fullImageSubresourceRange);
379
380 const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
381
382 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
383 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
384 buffer, 0ull, bufferSizeBytes);
385
386 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);
387 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ©Region);
388 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);
389 }
390
391 //! Copy all layers of a mipmap image to a buffer.
commandCopyMipmapImageToBuffer(Context & context,const VkCommandBuffer cmdBuffer,const VkImage image,const VkFormat imageFormat,const VkBuffer buffer,const VkDeviceSize bufferSizeBytes,const Texture & texture)392 void commandCopyMipmapImageToBuffer (Context& context,
393 const VkCommandBuffer cmdBuffer,
394 const VkImage image,
395 const VkFormat imageFormat,
396 const VkBuffer buffer,
397 const VkDeviceSize bufferSizeBytes,
398 const Texture& texture)
399 {
400 const DeviceInterface& vk = context.getDeviceInterface();
401
402 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
403 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
404 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
405 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
406 image, fullImageSubresourceRange);
407
408 std::vector<VkBufferImageCopy> copyRegions;
409 VkDeviceSize bufferOffset = 0u;
410 for (deInt32 levelNdx = 0; levelNdx < texture.numMipmapLevels(); levelNdx++)
411 {
412 const VkBufferImageCopy copyParams =
413 {
414 bufferOffset, // VkDeviceSize bufferOffset;
415 0u, // deUint32 bufferRowLength;
416 0u, // deUint32 bufferImageHeight;
417 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
418 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
419 makeExtent3D(texture.layerSize(levelNdx)), // VkExtent3D imageExtent;
420 };
421 copyRegions.push_back(copyParams);
422 bufferOffset += getMipmapLevelImageSizeBytes(texture, imageFormat, levelNdx);
423 }
424
425 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
426 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
427 buffer, 0ull, bufferSizeBytes);
428
429 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);
430 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, (deUint32) copyRegions.size(), copyRegions.data());
431 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);
432 }
433
434 class StoreTest : public TestCase
435 {
436 public:
437 enum TestFlags
438 {
439 FLAG_SINGLE_LAYER_BIND = 0x1, //!< Run the shader multiple times, each time binding a different layer.
440 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 0x2, //!< Declare the format of the images in the shader code
441 FLAG_MINALIGN = 0x4, //!< Use bufferview offset that matches the advertised minimum alignment
442 };
443
444 StoreTest (tcu::TestContext& testCtx,
445 const std::string& name,
446 const std::string& description,
447 const Texture& texture,
448 const VkFormat format,
449 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
450
451 virtual void checkSupport (Context& context) const;
452 void initPrograms (SourceCollections& programCollection) const;
453 TestInstance* createInstance (Context& context) const;
454
455 private:
456 const Texture m_texture;
457 const VkFormat m_format;
458 const bool m_declareImageFormatInShader;
459 const bool m_singleLayerBind;
460 const bool m_minalign;
461 };
462
StoreTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const Texture & texture,const VkFormat format,const deUint32 flags)463 StoreTest::StoreTest (tcu::TestContext& testCtx,
464 const std::string& name,
465 const std::string& description,
466 const Texture& texture,
467 const VkFormat format,
468 const deUint32 flags)
469 : TestCase (testCtx, name, description)
470 , m_texture (texture)
471 , m_format (format)
472 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
473 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
474 , m_minalign ((flags & FLAG_MINALIGN) != 0)
475 {
476 if (m_singleLayerBind)
477 DE_ASSERT(m_texture.numLayers() > 1);
478 }
479
checkSupport(Context & context) const480 void StoreTest::checkSupport (Context& context) const
481 {
482 const VkFormatProperties formatProperties (getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_format));
483
484 if (!m_declareImageFormatInShader)
485 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
486
487 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
488 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
489
490 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
491 TCU_THROW(NotSupportedError, "Format not supported for storage images");
492
493 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
494 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
495 }
496
initPrograms(SourceCollections & programCollection) const497 void StoreTest::initPrograms (SourceCollections& programCollection) const
498 {
499 const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
500 const float storeColorBias = computeStoreColorBias(m_format);
501 DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
502
503 const deUint32 xMax = m_texture.size().x() - 1;
504 const deUint32 yMax = m_texture.size().y() - 1;
505 const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
506 const bool storeNegativeValues = isSignedFormat(m_format) && (storeColorBias == 0);
507 bool useClamp = false;
508 std::string colorBaseExpr = signednessPrefix + "vec4("
509 + "gx^gy^gz, "
510 + "(" + de::toString(xMax) + "-gx)^gy^gz, "
511 + "gx^(" + de::toString(yMax) + "-gy)^gz, "
512 + "(" + de::toString(xMax) + "-gx)^(" + de::toString(yMax) + "-gy)^gz)";
513
514 // Large integer values may not be represented with formats with low bit depths
515 if (isIntegerFormat(m_format))
516 {
517 const deInt64 minStoreValue = storeNegativeValues ? 0 - deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : 0;
518 const deInt64 maxStoreValue = storeNegativeValues ? deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : de::max(xMax, yMax);
519
520 useClamp = !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(minStoreValue), mapVkFormat(m_format)) ||
521 !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(maxStoreValue), mapVkFormat(m_format));
522 }
523
524 // Clamp if integer value cannot be represented with the current format
525 if (useClamp)
526 {
527 const tcu::IVec4 bitDepths = tcu::getTextureFormatBitDepth(mapVkFormat(m_format));
528 tcu::IVec4 minRepresentableValue;
529 tcu::IVec4 maxRepresentableValue;
530
531 switch (tcu::getTextureChannelClass(mapVkFormat(m_format).type))
532 {
533 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
534 {
535 minRepresentableValue = tcu::IVec4(0);
536 maxRepresentableValue = (tcu::IVec4(1) << bitDepths) - tcu::IVec4(1);
537 break;
538 }
539
540 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
541 {
542 minRepresentableValue = -(tcu::IVec4(1) << bitDepths - tcu::IVec4(1));
543 maxRepresentableValue = (tcu::IVec4(1) << (bitDepths - tcu::IVec4(1))) - tcu::IVec4(1);
544 break;
545 }
546
547 default:
548 DE_ASSERT(isIntegerFormat(m_format));
549 }
550
551 colorBaseExpr = "clamp(" + colorBaseExpr + ", "
552 + signednessPrefix + "vec4" + de::toString(minRepresentableValue) + ", "
553 + signednessPrefix + "vec4" + de::toString(maxRepresentableValue) + ")";
554 }
555
556 std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
557 + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
558
559 if (storeNegativeValues)
560 colorExpr += "-" + de::toString(deRoundFloatToInt32((float)deMax32(xMax, yMax) / 2.0f));
561
562 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
563 const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
564
565 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
566 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
567 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
568
569 std::ostringstream src;
570 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
571 << "\n"
572 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
573 if (m_declareImageFormatInShader)
574 src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
575 else
576 src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n";
577
578 if (m_singleLayerBind)
579 src << "layout (binding = 1) readonly uniform Constants {\n"
580 << " int u_layerNdx;\n"
581 << "};\n";
582
583 src << "\n"
584 << "void main (void)\n"
585 << "{\n"
586 << " int gx = int(gl_GlobalInvocationID.x);\n"
587 << " int gy = int(gl_GlobalInvocationID.y);\n"
588 << " int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
589 << " imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
590 << "}\n";
591
592 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
593 }
594
595 //! Generic test iteration algorithm for image tests
596 class BaseTestInstance : public TestInstance
597 {
598 public:
599 BaseTestInstance (Context& context,
600 const Texture& texture,
601 const VkFormat format,
602 const bool declareImageFormatInShader,
603 const bool singleLayerBind,
604 const bool minalign,
605 const bool bufferLoadUniform);
606
607 tcu::TestStatus iterate (void);
608
~BaseTestInstance(void)609 virtual ~BaseTestInstance (void) {}
610
611 protected:
612 virtual VkDescriptorSetLayout prepareDescriptors (void) = 0;
613 virtual tcu::TestStatus verifyResult (void) = 0;
614
615 virtual void commandBeforeCompute (const VkCommandBuffer cmdBuffer) = 0;
616 virtual void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer) = 0;
617 virtual void commandAfterCompute (const VkCommandBuffer cmdBuffer) = 0;
618
619 virtual void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
620 const VkPipelineLayout pipelineLayout,
621 const int layerNdx) = 0;
622 virtual deUint32 getViewOffset (Context& context,
623 const VkFormat format,
624 bool uniform);
625
626 const Texture m_texture;
627 const VkFormat m_format;
628 const bool m_declareImageFormatInShader;
629 const bool m_singleLayerBind;
630 const bool m_minalign;
631 const bool m_bufferLoadUniform;
632 const deUint32 m_srcViewOffset;
633 const deUint32 m_dstViewOffset;
634 };
635
BaseTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool bufferLoadUniform)636 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign, const bool bufferLoadUniform)
637 : TestInstance (context)
638 , m_texture (texture)
639 , m_format (format)
640 , m_declareImageFormatInShader (declareImageFormatInShader)
641 , m_singleLayerBind (singleLayerBind)
642 , m_minalign (minalign)
643 , m_bufferLoadUniform (bufferLoadUniform)
644 , m_srcViewOffset (getViewOffset(context, format, m_bufferLoadUniform))
645 , m_dstViewOffset (getViewOffset(context, formatHasThreeComponents(format) ? getSingleComponentFormat(format) : format, false))
646 {
647 }
648
iterate(void)649 tcu::TestStatus BaseTestInstance::iterate (void)
650 {
651 const DeviceInterface& vk = m_context.getDeviceInterface();
652 const VkDevice device = m_context.getDevice();
653 const VkQueue queue = m_context.getUniversalQueue();
654 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
655
656 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
657
658 const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
659 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
660 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
661
662 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
663 const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
664
665 beginCommandBuffer(vk, *cmdBuffer);
666
667 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
668 commandBeforeCompute(*cmdBuffer);
669
670 const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
671 const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
672 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
673 {
674 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
675
676 if (layerNdx > 0)
677 commandBetweenShaderInvocations(*cmdBuffer);
678
679 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
680 }
681
682 commandAfterCompute(*cmdBuffer);
683
684 endCommandBuffer(vk, *cmdBuffer);
685
686 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
687
688 return verifyResult();
689 }
690
691 //! Base store test implementation
692 class StoreTestInstance : public BaseTestInstance
693 {
694 public:
695 StoreTestInstance (Context& context,
696 const Texture& texture,
697 const VkFormat format,
698 const bool declareImageFormatInShader,
699 const bool singleLayerBind,
700 const bool minalign);
701
702 protected:
703 virtual tcu::TestStatus verifyResult (void);
704
705 // Add empty implementations for functions that might be not needed
commandBeforeCompute(const VkCommandBuffer)706 void commandBeforeCompute (const VkCommandBuffer) {}
commandBetweenShaderInvocations(const VkCommandBuffer)707 void commandBetweenShaderInvocations (const VkCommandBuffer) {}
commandAfterCompute(const VkCommandBuffer)708 void commandAfterCompute (const VkCommandBuffer) {}
709
710 de::MovePtr<Buffer> m_imageBuffer;
711 const VkDeviceSize m_imageSizeBytes;
712 };
713
getViewOffset(Context & context,const VkFormat format,bool uniform)714 deUint32 BaseTestInstance::getViewOffset(Context& context,
715 const VkFormat format,
716 bool uniform)
717 {
718 if (m_minalign)
719 {
720 if (!context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
721 return (deUint32)context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
722
723 VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties;
724 deMemset(&alignmentProperties, 0, sizeof(alignmentProperties));
725 alignmentProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
726
727 VkPhysicalDeviceProperties2 properties2;
728 deMemset(&properties2, 0, sizeof(properties2));
729 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
730 properties2.pNext = &alignmentProperties;
731
732 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
733
734 VkBool32 singleTexelAlignment = uniform ? alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
735 alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
736 VkDeviceSize align = uniform ? alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
737 alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
738
739 VkDeviceSize texelSize = formatHasThreeComponents(format) ? tcu::getChannelSize(vk::mapVkFormat(format).type) : tcu::getPixelSize(vk::mapVkFormat(format));
740
741 if (singleTexelAlignment)
742 align = de::min(align, texelSize);
743
744 return (deUint32)align;
745 }
746
747 return 0;
748 }
749
StoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign)750 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign)
751 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, false)
752 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format))
753 {
754 const DeviceInterface& vk = m_context.getDeviceInterface();
755 const VkDevice device = m_context.getDevice();
756 Allocator& allocator = m_context.getDefaultAllocator();
757
758 // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
759
760 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
761 vk, device, allocator,
762 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
763 MemoryRequirement::HostVisible));
764 }
765
verifyResult(void)766 tcu::TestStatus StoreTestInstance::verifyResult (void)
767 {
768 const DeviceInterface& vk = m_context.getDeviceInterface();
769 const VkDevice device = m_context.getDevice();
770
771 const tcu::IVec3 imageSize = m_texture.size();
772 const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format);
773
774 const Allocation& alloc = m_imageBuffer->getAllocation();
775 invalidateAlloc(vk, device, alloc);
776 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, (const char *)alloc.getHostPtr() + m_dstViewOffset);
777
778 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
779 return tcu::TestStatus::pass("Passed");
780 else
781 return tcu::TestStatus::fail("Image comparison failed");
782 }
783
784 //! Store test for images
785 class ImageStoreTestInstance : public StoreTestInstance
786 {
787 public:
788 ImageStoreTestInstance (Context& context,
789 const Texture& texture,
790 const VkFormat format,
791 const bool declareImageFormatInShader,
792 const bool singleLayerBind,
793 const bool minalign);
794
795 protected:
796 VkDescriptorSetLayout prepareDescriptors (void);
797 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
798 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
799 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
800
801 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
802 const VkPipelineLayout pipelineLayout,
803 const int layerNdx);
804
805 de::MovePtr<Image> m_image;
806 de::MovePtr<Buffer> m_constantsBuffer;
807 const VkDeviceSize m_constantsBufferChunkSizeBytes;
808 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
809 Move<VkDescriptorPool> m_descriptorPool;
810 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
811 std::vector<SharedVkImageView> m_allImageViews;
812 };
813
ImageStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign)814 ImageStoreTestInstance::ImageStoreTestInstance (Context& context,
815 const Texture& texture,
816 const VkFormat format,
817 const bool declareImageFormatInShader,
818 const bool singleLayerBind,
819 const bool minalign)
820 : StoreTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign)
821 , m_constantsBufferChunkSizeBytes (getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32)))
822 , m_allDescriptorSets (texture.numLayers())
823 , m_allImageViews (texture.numLayers())
824 {
825 const DeviceInterface& vk = m_context.getDeviceInterface();
826 const VkDevice device = m_context.getDevice();
827 Allocator& allocator = m_context.getDefaultAllocator();
828
829 m_image = de::MovePtr<Image>(new Image(
830 vk, device, allocator,
831 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
832 MemoryRequirement::Any));
833
834 // This buffer will be used to pass constants to the shader
835
836 const int numLayers = m_texture.numLayers();
837 const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
838 m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
839 vk, device, allocator,
840 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
841 MemoryRequirement::HostVisible));
842
843 {
844 const Allocation& alloc = m_constantsBuffer->getAllocation();
845 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
846
847 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
848
849 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
850 {
851 deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
852 *valuePtr = static_cast<deUint32>(layerNdx);
853 }
854
855 flushAlloc(vk, device, alloc);
856 }
857 }
858
prepareDescriptors(void)859 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
860 {
861 const DeviceInterface& vk = m_context.getDeviceInterface();
862 const VkDevice device = m_context.getDevice();
863
864 const int numLayers = m_texture.numLayers();
865 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
866 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
867 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
868 .build(vk, device);
869
870 m_descriptorPool = DescriptorPoolBuilder()
871 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
872 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
873 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
874
875 if (m_singleLayerBind)
876 {
877 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
878 {
879 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
880 m_allImageViews[layerNdx] = makeVkSharedPtr(makeImageView(
881 vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
882 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
883 }
884 }
885 else // bind all layers at once
886 {
887 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
888 m_allImageViews[0] = makeVkSharedPtr(makeImageView(
889 vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
890 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
891 }
892
893 return *m_descriptorSetLayout; // not passing the ownership
894 }
895
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)896 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
897 {
898 const DeviceInterface& vk = m_context.getDeviceInterface();
899 const VkDevice device = m_context.getDevice();
900
901 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
902 const VkImageView imageView = **m_allImageViews[layerNdx];
903
904 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
905
906 // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
907 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
908 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
909
910 DescriptorSetUpdateBuilder()
911 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
912 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
913 .update(vk, device);
914 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
915 }
916
commandBeforeCompute(const VkCommandBuffer cmdBuffer)917 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
918 {
919 const DeviceInterface& vk = m_context.getDeviceInterface();
920
921 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
922 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
923 0u, VK_ACCESS_SHADER_WRITE_BIT,
924 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
925 m_image->get(), fullImageSubresourceRange);
926
927 const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
928 const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
929 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
930 m_constantsBuffer->get(), 0ull, constantsBufferSize);
931
932 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);
933 }
934
commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)935 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
936 {
937 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
938 }
939
commandAfterCompute(const VkCommandBuffer cmdBuffer)940 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
941 {
942 commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
943 }
944
945 //! Store test for buffers
946 class BufferStoreTestInstance : public StoreTestInstance
947 {
948 public:
949 BufferStoreTestInstance (Context& context,
950 const Texture& texture,
951 const VkFormat format,
952 const bool declareImageFormatInShader,
953 const bool minalign);
954
955 protected:
956 VkDescriptorSetLayout prepareDescriptors (void);
957 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
958
959 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
960 const VkPipelineLayout pipelineLayout,
961 const int layerNdx);
962
963 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
964 Move<VkDescriptorPool> m_descriptorPool;
965 Move<VkDescriptorSet> m_descriptorSet;
966 Move<VkBufferView> m_bufferView;
967 };
968
BufferStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool declareImageFormatInShader,const bool minalign)969 BufferStoreTestInstance::BufferStoreTestInstance (Context& context,
970 const Texture& texture,
971 const VkFormat format,
972 const bool declareImageFormatInShader,
973 const bool minalign)
974 : StoreTestInstance(context, texture, format, declareImageFormatInShader, false, minalign)
975 {
976 }
977
prepareDescriptors(void)978 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
979 {
980 const DeviceInterface& vk = m_context.getDeviceInterface();
981 const VkDevice device = m_context.getDevice();
982
983 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
984 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
985 .build(vk, device);
986
987 m_descriptorPool = DescriptorPoolBuilder()
988 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
989 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
990
991 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
992 m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_dstViewOffset, m_imageSizeBytes);
993
994 return *m_descriptorSetLayout; // not passing the ownership
995 }
996
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)997 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
998 {
999 DE_ASSERT(layerNdx == 0);
1000 DE_UNREF(layerNdx);
1001
1002 const VkDevice device = m_context.getDevice();
1003 const DeviceInterface& vk = m_context.getDeviceInterface();
1004
1005 DescriptorSetUpdateBuilder()
1006 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
1007 .update(vk, device);
1008 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1009 }
1010
commandAfterCompute(const VkCommandBuffer cmdBuffer)1011 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1012 {
1013 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes + m_dstViewOffset);
1014 }
1015
1016 class LoadStoreTest : public TestCase
1017 {
1018 public:
1019 enum TestFlags
1020 {
1021 FLAG_SINGLE_LAYER_BIND = 1 << 0, //!< Run the shader multiple times, each time binding a different layer.
1022 FLAG_RESTRICT_IMAGES = 1 << 1, //!< If given, images in the shader will be qualified with "restrict".
1023 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 1 << 2, //!< Declare the format of the images in the shader code
1024 FLAG_MINALIGN = 1 << 3, //!< Use bufferview offset that matches the advertised minimum alignment
1025 FLAG_UNIFORM_TEXEL_BUFFER = 1 << 4, //!< Load from a uniform texel buffer rather than a storage texel buffer
1026 };
1027
1028 LoadStoreTest (tcu::TestContext& testCtx,
1029 const std::string& name,
1030 const std::string& description,
1031 const Texture& texture,
1032 const VkFormat format,
1033 const VkFormat imageFormat,
1034 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER,
1035 const deBool imageLoadStoreLodAMD = DE_FALSE);
1036
1037 virtual void checkSupport (Context& context) const;
1038 void initPrograms (SourceCollections& programCollection) const;
1039 TestInstance* createInstance (Context& context) const;
1040
1041 private:
1042 const Texture m_texture;
1043 const VkFormat m_format; //!< Format as accessed in the shader
1044 const VkFormat m_imageFormat; //!< Storage format
1045 const bool m_declareImageFormatInShader; //!< Whether the shader will specify the format layout qualifier of the images
1046 const bool m_singleLayerBind;
1047 const bool m_restrictImages;
1048 const bool m_minalign;
1049 bool m_bufferLoadUniform;
1050 const deBool m_imageLoadStoreLodAMD;
1051 };
1052
LoadStoreTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const deUint32 flags,const deBool imageLoadStoreLodAMD)1053 LoadStoreTest::LoadStoreTest (tcu::TestContext& testCtx,
1054 const std::string& name,
1055 const std::string& description,
1056 const Texture& texture,
1057 const VkFormat format,
1058 const VkFormat imageFormat,
1059 const deUint32 flags,
1060 const deBool imageLoadStoreLodAMD)
1061 : TestCase (testCtx, name, description)
1062 , m_texture (texture)
1063 , m_format (format)
1064 , m_imageFormat (imageFormat)
1065 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
1066 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
1067 , m_restrictImages ((flags & FLAG_RESTRICT_IMAGES) != 0)
1068 , m_minalign ((flags & FLAG_MINALIGN) != 0)
1069 , m_bufferLoadUniform ((flags & FLAG_UNIFORM_TEXEL_BUFFER) != 0)
1070 , m_imageLoadStoreLodAMD (imageLoadStoreLodAMD)
1071 {
1072 if (m_singleLayerBind)
1073 DE_ASSERT(m_texture.numLayers() > 1);
1074
1075 DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
1076 }
1077
checkSupport(Context & context) const1078 void LoadStoreTest::checkSupport (Context& context) const
1079 {
1080 const vk::VkFormatProperties formatProperties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1081 context.getPhysicalDevice(),
1082 m_format));
1083 const vk::VkFormatProperties imageFormatProperties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1084 context.getPhysicalDevice(),
1085 m_imageFormat));
1086 if (m_imageLoadStoreLodAMD)
1087 context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1088
1089 if (!m_bufferLoadUniform && !m_declareImageFormatInShader)
1090 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT);
1091
1092 if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1093 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1094
1095 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1096 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1097
1098 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1099 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1100
1101 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageFormatProperties.optimalTilingFeatures))
1102 TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1103
1104 if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1105 TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1106
1107 if (formatHasThreeComponents(m_format))
1108 {
1109 // When the source buffer is three-component, the destination buffer is single-component.
1110 VkFormat dstFormat = getSingleComponentFormat(m_format);
1111 const vk::VkFormatProperties dstFormatProperties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1112 context.getPhysicalDevice(),
1113 dstFormat));
1114
1115 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1116 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1117 }
1118 else
1119 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1120 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1121
1122 if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1123 TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1124 }
1125
initPrograms(SourceCollections & programCollection) const1126 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
1127 {
1128 const tcu::TextureFormat texFormat = mapVkFormat(m_format);
1129 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
1130 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
1131 const std::string formatQualifierStr = getShaderImageFormatQualifier(texFormat);
1132 const std::string uniformTypeStr = getFormatPrefix(texFormat) + "textureBuffer";
1133 const std::string imageTypeStr = getShaderImageType(texFormat, usedImageType);
1134 const std::string maybeRestrictStr = (m_restrictImages ? "restrict " : "");
1135 const std::string xMax = de::toString(m_texture.size().x() - 1);
1136
1137 std::ostringstream src;
1138 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1139 << "\n";
1140 if (!m_declareImageFormatInShader)
1141 {
1142 src << "#extension GL_EXT_shader_image_load_formatted : require\n";
1143 }
1144
1145 if (m_imageLoadStoreLodAMD)
1146 {
1147 src << "#extension GL_AMD_shader_image_load_store_lod : require\n";
1148 }
1149
1150 src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
1151 if (m_bufferLoadUniform)
1152 src << "layout (binding = 0) uniform " << uniformTypeStr << " u_image0;\n";
1153 else if (m_declareImageFormatInShader)
1154 src << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1155 else
1156 src << "layout (binding = 0) " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1157
1158 if (formatHasThreeComponents(m_format))
1159 src << "layout (binding = 1) " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1160 else
1161 src << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1162
1163 src << "\n"
1164 << "void main (void)\n"
1165 << "{\n";
1166 switch (dimension)
1167 {
1168 default: DE_ASSERT(0); // fallthrough
1169 case 1:
1170 if (m_bufferLoadUniform)
1171 {
1172 // for three-component formats, the dst buffer is single-component and the shader
1173 // expands the store into 3 component-wise stores.
1174 std::string type = getFormatPrefix(texFormat) + "vec4";
1175 src << " int pos = int(gl_GlobalInvocationID.x);\n"
1176 " " << type << " t = texelFetch(u_image0, " + xMax + "-pos);\n";
1177 if (formatHasThreeComponents(m_format))
1178 {
1179 src << " imageStore(u_image1, 3*pos+0, " << type << "(t.x));\n";
1180 src << " imageStore(u_image1, 3*pos+1, " << type << "(t.y));\n";
1181 src << " imageStore(u_image1, 3*pos+2, " << type << "(t.z));\n";
1182 }
1183 else
1184 src << " imageStore(u_image1, pos, t);\n";
1185 }
1186 else if (m_imageLoadStoreLodAMD)
1187 {
1188 src <<
1189 " int pos = int(gl_GlobalInvocationID.x);\n";
1190
1191 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1192 {
1193 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1194 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, " + xMaxSize + "-pos, " + de::toString(levelNdx) + "));\n";
1195 }
1196 }
1197 else
1198 {
1199 src <<
1200 " int pos = int(gl_GlobalInvocationID.x);\n"
1201 " imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n";
1202 }
1203 break;
1204 case 2:
1205 if (m_imageLoadStoreLodAMD)
1206 {
1207 src << " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
1208
1209 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1210 {
1211 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1212 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec2(" + xMaxSize + "-pos.x, pos.y), " + de::toString(levelNdx) + "));\n";
1213 }
1214
1215 }
1216 else
1217 {
1218 src <<
1219 " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
1220 " imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n";
1221 }
1222 break;
1223 case 3:
1224 if (m_imageLoadStoreLodAMD)
1225 {
1226 src << " ivec3 pos = ivec3(gl_GlobalInvocationID);\n";
1227
1228 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1229 {
1230 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1231 src << " imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec3(" + xMaxSize + "-pos.x, pos.y, pos.z), " + de::toString(levelNdx) + "));\n";
1232 }
1233 }
1234 else
1235 {
1236 src <<
1237 " ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
1238 " imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n";
1239 }
1240 break;
1241 }
1242 src << "}\n";
1243
1244 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1245 }
1246
1247 //! Load/store test base implementation
1248 class LoadStoreTestInstance : public BaseTestInstance
1249 {
1250 public:
1251 LoadStoreTestInstance (Context& context,
1252 const Texture& texture,
1253 const VkFormat format,
1254 const VkFormat imageFormat,
1255 const bool declareImageFormatInShader,
1256 const bool singleLayerBind,
1257 const bool minalign,
1258 const bool bufferLoadUniform);
1259
1260 protected:
1261 virtual Buffer* getResultBuffer (void) const = 0; //!< Get the buffer that contains the result image
1262
1263 tcu::TestStatus verifyResult (void);
1264
1265 // Add empty implementations for functions that might be not needed
commandBeforeCompute(const VkCommandBuffer)1266 void commandBeforeCompute (const VkCommandBuffer) {}
commandBetweenShaderInvocations(const VkCommandBuffer)1267 void commandBetweenShaderInvocations (const VkCommandBuffer) {}
commandAfterCompute(const VkCommandBuffer)1268 void commandAfterCompute (const VkCommandBuffer) {}
1269
1270 de::MovePtr<Buffer> m_imageBuffer; //!< Source data and helper buffer
1271 const VkDeviceSize m_imageSizeBytes;
1272 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
1273 tcu::TextureLevel m_referenceImage; //!< Used as input data and later to verify result image
1274
1275 bool m_bufferLoadUniform;
1276 VkDescriptorType m_bufferLoadDescriptorType;
1277 VkBufferUsageFlagBits m_bufferLoadUsageBit;
1278 };
1279
LoadStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool bufferLoadUniform)1280 LoadStoreTestInstance::LoadStoreTestInstance (Context& context,
1281 const Texture& texture,
1282 const VkFormat format,
1283 const VkFormat imageFormat,
1284 const bool declareImageFormatInShader,
1285 const bool singleLayerBind,
1286 const bool minalign,
1287 const bool bufferLoadUniform)
1288 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1289 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format))
1290 , m_imageFormat (imageFormat)
1291 , m_referenceImage (generateReferenceImage(texture.size(), imageFormat, format))
1292 , m_bufferLoadUniform (bufferLoadUniform)
1293 {
1294 const DeviceInterface& vk = m_context.getDeviceInterface();
1295 const VkDevice device = m_context.getDevice();
1296 Allocator& allocator = m_context.getDefaultAllocator();
1297
1298 m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1299 m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1300
1301 // A helper buffer with enough space to hold the whole image.
1302
1303 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
1304 vk, device, allocator,
1305 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1306 MemoryRequirement::HostVisible));
1307
1308 // Copy reference data to buffer for subsequent upload to image.
1309
1310 const Allocation& alloc = m_imageBuffer->getAllocation();
1311 deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset, m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
1312 flushAlloc(vk, device, alloc);
1313 }
1314
verifyResult(void)1315 tcu::TestStatus LoadStoreTestInstance::verifyResult (void)
1316 {
1317 const DeviceInterface& vk = m_context.getDeviceInterface();
1318 const VkDevice device = m_context.getDevice();
1319
1320 // Apply the same transformation as done in the shader
1321 const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
1322 flipHorizontally(reference);
1323
1324 const Allocation& alloc = getResultBuffer()->getAllocation();
1325 invalidateAlloc(vk, device, alloc);
1326 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), (const char *)alloc.getHostPtr() + m_dstViewOffset);
1327
1328 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
1329 return tcu::TestStatus::pass("Passed");
1330 else
1331 return tcu::TestStatus::fail("Image comparison failed");
1332 }
1333
1334 //! Load/store test for images
1335 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
1336 {
1337 public:
1338 ImageLoadStoreTestInstance (Context& context,
1339 const Texture& texture,
1340 const VkFormat format,
1341 const VkFormat imageFormat,
1342 const bool declareImageFormatInShader,
1343 const bool singleLayerBind,
1344 const bool minalign,
1345 const bool bufferLoadUniform);
1346
1347 protected:
1348 VkDescriptorSetLayout prepareDescriptors (void);
1349 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
1350 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
1351 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1352
1353 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1354 const VkPipelineLayout pipelineLayout,
1355 const int layerNdx);
1356
getResultBuffer(void) const1357 Buffer* getResultBuffer (void) const { return m_imageBuffer.get(); }
1358
1359 de::MovePtr<Image> m_imageSrc;
1360 de::MovePtr<Image> m_imageDst;
1361 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1362 Move<VkDescriptorPool> m_descriptorPool;
1363 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1364 std::vector<SharedVkImageView> m_allSrcImageViews;
1365 std::vector<SharedVkImageView> m_allDstImageViews;
1366 };
1367
ImageLoadStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool bufferLoadUniform)1368 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context& context,
1369 const Texture& texture,
1370 const VkFormat format,
1371 const VkFormat imageFormat,
1372 const bool declareImageFormatInShader,
1373 const bool singleLayerBind,
1374 const bool minalign,
1375 const bool bufferLoadUniform)
1376 : LoadStoreTestInstance (context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1377 , m_allDescriptorSets (texture.numLayers())
1378 , m_allSrcImageViews (texture.numLayers())
1379 , m_allDstImageViews (texture.numLayers())
1380 {
1381 const DeviceInterface& vk = m_context.getDeviceInterface();
1382 const VkDevice device = m_context.getDevice();
1383 Allocator& allocator = m_context.getDefaultAllocator();
1384 const VkImageCreateFlags imageFlags = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1385
1386 m_imageSrc = de::MovePtr<Image>(new Image(
1387 vk, device, allocator,
1388 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags),
1389 MemoryRequirement::Any));
1390
1391 m_imageDst = de::MovePtr<Image>(new Image(
1392 vk, device, allocator,
1393 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags),
1394 MemoryRequirement::Any));
1395 }
1396
prepareDescriptors(void)1397 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1398 {
1399 const VkDevice device = m_context.getDevice();
1400 const DeviceInterface& vk = m_context.getDeviceInterface();
1401
1402 const int numLayers = m_texture.numLayers();
1403 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1404 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1405 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1406 .build(vk, device);
1407
1408 m_descriptorPool = DescriptorPoolBuilder()
1409 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1410 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1411 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1412
1413 if (m_singleLayerBind)
1414 {
1415 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1416 {
1417 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1418 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1419
1420 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1421 m_allSrcImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1422 m_allDstImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1423 }
1424 }
1425 else // bind all layers at once
1426 {
1427 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1428 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1429
1430 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1431 m_allSrcImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1432 m_allDstImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1433 }
1434
1435 return *m_descriptorSetLayout; // not passing the ownership
1436 }
1437
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)1438 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1439 {
1440 const VkDevice device = m_context.getDevice();
1441 const DeviceInterface& vk = m_context.getDeviceInterface();
1442
1443 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1444 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
1445 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
1446
1447 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1448 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1449
1450 DescriptorSetUpdateBuilder()
1451 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1452 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1453 .update(vk, device);
1454 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1455 }
1456
commandBeforeCompute(const VkCommandBuffer cmdBuffer)1457 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1458 {
1459 const DeviceInterface& vk = m_context.getDeviceInterface();
1460
1461 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1462 {
1463 const VkImageMemoryBarrier preCopyImageBarriers[] =
1464 {
1465 makeImageMemoryBarrier(
1466 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1467 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1468 m_imageSrc->get(), fullImageSubresourceRange),
1469 makeImageMemoryBarrier(
1470 0u, VK_ACCESS_SHADER_WRITE_BIT,
1471 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1472 m_imageDst->get(), fullImageSubresourceRange)
1473 };
1474
1475 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1476 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1477 m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1478
1479 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1480 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1481 }
1482 {
1483 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1484 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1485 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1486 m_imageSrc->get(), fullImageSubresourceRange);
1487
1488 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1489
1490 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
1491 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);
1492 }
1493 }
1494
commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)1495 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1496 {
1497 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1498 }
1499
commandAfterCompute(const VkCommandBuffer cmdBuffer)1500 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1501 {
1502 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1503 }
1504
1505 //! Load/store Lod AMD test for images
1506 class ImageLoadStoreLodAMDTestInstance : public BaseTestInstance
1507 {
1508 public:
1509 ImageLoadStoreLodAMDTestInstance (Context& context,
1510 const Texture& texture,
1511 const VkFormat format,
1512 const VkFormat imageFormat,
1513 const bool declareImageFormatInShader,
1514 const bool singleLayerBind,
1515 const bool minalign,
1516 const bool bufferLoadUniform);
1517
1518 protected:
1519 VkDescriptorSetLayout prepareDescriptors (void);
1520 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
1521 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
1522 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1523
1524 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1525 const VkPipelineLayout pipelineLayout,
1526 const int layerNdx);
1527
getResultBuffer(void) const1528 Buffer* getResultBuffer (void) const { return m_imageBuffer.get(); }
1529 tcu::TestStatus verifyResult (void);
1530
1531 de::MovePtr<Buffer> m_imageBuffer; //!< Source data and helper buffer
1532 const VkDeviceSize m_imageSizeBytes;
1533 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
1534 std::vector<tcu::TextureLevel> m_referenceImages; //!< Used as input data and later to verify result image
1535
1536 bool m_bufferLoadUniform;
1537 VkDescriptorType m_bufferLoadDescriptorType;
1538 VkBufferUsageFlagBits m_bufferLoadUsageBit;
1539
1540 de::MovePtr<Image> m_imageSrc;
1541 de::MovePtr<Image> m_imageDst;
1542 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1543 Move<VkDescriptorPool> m_descriptorPool;
1544 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1545 std::vector<SharedVkImageView> m_allSrcImageViews;
1546 std::vector<SharedVkImageView> m_allDstImageViews;
1547
1548 };
1549
ImageLoadStoreLodAMDTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const bool declareImageFormatInShader,const bool singleLayerBind,const bool minalign,const bool bufferLoadUniform)1550 ImageLoadStoreLodAMDTestInstance::ImageLoadStoreLodAMDTestInstance (Context& context,
1551 const Texture& texture,
1552 const VkFormat format,
1553 const VkFormat imageFormat,
1554 const bool declareImageFormatInShader,
1555 const bool singleLayerBind,
1556 const bool minalign,
1557 const bool bufferLoadUniform)
1558 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1559 , m_imageSizeBytes (getMipmapImageTotalSizeBytes(texture, format))
1560 , m_imageFormat (imageFormat)
1561 , m_bufferLoadUniform (bufferLoadUniform)
1562 , m_allDescriptorSets (texture.numLayers())
1563 , m_allSrcImageViews (texture.numLayers())
1564 , m_allDstImageViews (texture.numLayers())
1565 {
1566 const DeviceInterface& vk = m_context.getDeviceInterface();
1567 const VkDevice device = m_context.getDevice();
1568 Allocator& allocator = m_context.getDefaultAllocator();
1569 const VkImageCreateFlags imageFlags = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1570
1571 const VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(m_texture.numSamples()); // integer and bit mask are aligned, so we can cast like this
1572
1573 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1574 {
1575 tcu::TextureLevel referenceImage = generateReferenceImage(texture.size(levelNdx), imageFormat, format);
1576 m_referenceImages.push_back(referenceImage);
1577 }
1578
1579 m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1580 m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1581
1582 // A helper buffer with enough space to hold the whole image.
1583 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
1584 vk, device, allocator,
1585 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1586 MemoryRequirement::HostVisible));
1587
1588 // Copy reference data to buffer for subsequent upload to image.
1589 {
1590 const Allocation& alloc = m_imageBuffer->getAllocation();
1591 VkDeviceSize bufferOffset = 0u;
1592 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1593 {
1594 deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset + bufferOffset, m_referenceImages[levelNdx].getAccess().getDataPtr(), static_cast<size_t>(getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx)));
1595 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1596 }
1597 flushAlloc(vk, device, alloc);
1598 }
1599
1600 {
1601 const VkImageCreateInfo imageParamsSrc =
1602 {
1603 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1604 DE_NULL, // const void* pNext;
1605 (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags, // VkImageCreateFlags flags;
1606 mapImageType(m_texture.type()), // VkImageType imageType;
1607 m_imageFormat, // VkFormat format;
1608 makeExtent3D(m_texture.layerSize()), // VkExtent3D extent;
1609 (deUint32)m_texture.numMipmapLevels(), // deUint32 mipLevels;
1610 (deUint32)m_texture.numLayers(), // deUint32 arrayLayers;
1611 samples, // VkSampleCountFlagBits samples;
1612 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1613 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
1614 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1615 0u, // deUint32 queueFamilyIndexCount;
1616 DE_NULL, // const deUint32* pQueueFamilyIndices;
1617 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1618 };
1619
1620 m_imageSrc = de::MovePtr<Image>(new Image(
1621 vk, device, allocator,
1622 imageParamsSrc,
1623 MemoryRequirement::Any));
1624 }
1625
1626 {
1627 const VkImageCreateInfo imageParamsDst =
1628 {
1629 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1630 DE_NULL, // const void* pNext;
1631 (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags, // VkImageCreateFlags flags;
1632 mapImageType(m_texture.type()), // VkImageType imageType;
1633 m_imageFormat, // VkFormat format;
1634 makeExtent3D(m_texture.layerSize()), // VkExtent3D extent;
1635 (deUint32)m_texture.numMipmapLevels(), // deUint32 mipLevels;
1636 (deUint32)m_texture.numLayers(), // deUint32 arrayLayers;
1637 samples, // VkSampleCountFlagBits samples;
1638 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1639 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1640 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1641 0u, // deUint32 queueFamilyIndexCount;
1642 DE_NULL, // const deUint32* pQueueFamilyIndices;
1643 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1644 };
1645
1646 m_imageDst = de::MovePtr<Image>(new Image(
1647 vk, device, allocator,
1648 imageParamsDst,
1649 MemoryRequirement::Any));
1650 }
1651 }
1652
verifyResult(void)1653 tcu::TestStatus ImageLoadStoreLodAMDTestInstance::verifyResult (void)
1654 {
1655 const DeviceInterface& vk = m_context.getDeviceInterface();
1656 const VkDevice device = m_context.getDevice();
1657
1658 const Allocation& alloc = getResultBuffer()->getAllocation();
1659 invalidateAlloc(vk, device, alloc);
1660
1661 VkDeviceSize bufferOffset = 0;
1662 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1663 {
1664 // Apply the same transformation as done in the shader
1665 const tcu::PixelBufferAccess reference = m_referenceImages[levelNdx].getAccess();
1666 flipHorizontally(reference);
1667
1668 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(levelNdx), (const char *)alloc.getHostPtr() + m_dstViewOffset + bufferOffset);
1669
1670 if (!comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result, levelNdx))
1671 {
1672 std::ostringstream errorMessage;
1673 errorMessage << "Image Level " << levelNdx << " comparison failed";
1674 return tcu::TestStatus::fail(errorMessage.str());
1675 }
1676 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1677 }
1678
1679 return tcu::TestStatus::pass("Passed");
1680 }
1681
prepareDescriptors(void)1682 VkDescriptorSetLayout ImageLoadStoreLodAMDTestInstance::prepareDescriptors (void)
1683 {
1684 const VkDevice device = m_context.getDevice();
1685 const DeviceInterface& vk = m_context.getDeviceInterface();
1686
1687 const int numLayers = m_texture.numLayers();
1688 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1689 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1690 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1691 .build(vk, device);
1692
1693 m_descriptorPool = DescriptorPoolBuilder()
1694 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1695 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1696 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1697
1698 if (m_singleLayerBind)
1699 {
1700 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1701 {
1702 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1703 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), layerNdx, 1u);
1704
1705 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1706 m_allSrcImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1707 m_allDstImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1708 }
1709 }
1710 else // bind all layers at once
1711 {
1712 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1713 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, numLayers);
1714
1715 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1716 m_allSrcImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1717 m_allDstImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1718 }
1719
1720 return *m_descriptorSetLayout; // not passing the ownership
1721 }
1722
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)1723 void ImageLoadStoreLodAMDTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1724 {
1725 const VkDevice device = m_context.getDevice();
1726 const DeviceInterface& vk = m_context.getDeviceInterface();
1727
1728 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1729 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
1730 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
1731
1732 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1733 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1734
1735 DescriptorSetUpdateBuilder()
1736 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1737 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1738 .update(vk, device);
1739 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1740 }
1741
commandBeforeCompute(const VkCommandBuffer cmdBuffer)1742 void ImageLoadStoreLodAMDTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1743 {
1744 const DeviceInterface& vk = m_context.getDeviceInterface();
1745 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, m_texture.numLayers());
1746 {
1747 const VkImageMemoryBarrier preCopyImageBarriers[] =
1748 {
1749 makeImageMemoryBarrier(
1750 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1751 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1752 m_imageSrc->get(), fullImageSubresourceRange),
1753 makeImageMemoryBarrier(
1754 0u, VK_ACCESS_SHADER_WRITE_BIT,
1755 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1756 m_imageDst->get(), fullImageSubresourceRange)
1757 };
1758
1759 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1760 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1761 m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1762
1763 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1764 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1765 }
1766 {
1767 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1768 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1769 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1770 m_imageSrc->get(), fullImageSubresourceRange);
1771
1772 std::vector<VkBufferImageCopy> copyRegions;
1773 VkDeviceSize bufferOffset = 0u;
1774 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1775 {
1776 const VkBufferImageCopy copyParams =
1777 {
1778 bufferOffset, // VkDeviceSize bufferOffset;
1779 0u, // deUint32 bufferRowLength;
1780 0u, // deUint32 bufferImageHeight;
1781 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, m_texture.numLayers()), // VkImageSubresourceLayers imageSubresource;
1782 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1783 makeExtent3D(m_texture.layerSize(levelNdx)), // VkExtent3D imageExtent;
1784 };
1785 copyRegions.push_back(copyParams);
1786 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1787 }
1788
1789 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32) copyRegions.size(), copyRegions.data());
1790 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);
1791 }
1792 }
1793
commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)1794 void ImageLoadStoreLodAMDTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1795 {
1796 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1797 }
1798
commandAfterCompute(const VkCommandBuffer cmdBuffer)1799 void ImageLoadStoreLodAMDTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1800 {
1801 commandCopyMipmapImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageFormat, m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1802 }
1803
1804 //! Load/store test for buffers
1805 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
1806 {
1807 public:
1808 BufferLoadStoreTestInstance (Context& context,
1809 const Texture& texture,
1810 const VkFormat format,
1811 const VkFormat imageFormat,
1812 const bool declareImageFormatInShader,
1813 const bool minalign,
1814 const bool bufferLoadUniform);
1815
1816 protected:
1817 VkDescriptorSetLayout prepareDescriptors (void);
1818 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1819
1820 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1821 const VkPipelineLayout pipelineLayout,
1822 const int layerNdx);
1823
getResultBuffer(void) const1824 Buffer* getResultBuffer (void) const { return m_imageBufferDst.get(); }
1825
1826 de::MovePtr<Buffer> m_imageBufferDst;
1827 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1828 Move<VkDescriptorPool> m_descriptorPool;
1829 Move<VkDescriptorSet> m_descriptorSet;
1830 Move<VkBufferView> m_bufferViewSrc;
1831 Move<VkBufferView> m_bufferViewDst;
1832 };
1833
BufferLoadStoreTestInstance(Context & context,const Texture & texture,const VkFormat format,const VkFormat imageFormat,const bool declareImageFormatInShader,const bool minalign,const bool bufferLoadUniform)1834 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context& context,
1835 const Texture& texture,
1836 const VkFormat format,
1837 const VkFormat imageFormat,
1838 const bool declareImageFormatInShader,
1839 const bool minalign,
1840 const bool bufferLoadUniform)
1841 : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false, minalign, bufferLoadUniform)
1842 {
1843 const DeviceInterface& vk = m_context.getDeviceInterface();
1844 const VkDevice device = m_context.getDevice();
1845 Allocator& allocator = m_context.getDefaultAllocator();
1846
1847 // Create a destination buffer.
1848
1849 m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
1850 vk, device, allocator,
1851 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
1852 MemoryRequirement::HostVisible));
1853 }
1854
prepareDescriptors(void)1855 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
1856 {
1857 const DeviceInterface& vk = m_context.getDeviceInterface();
1858 const VkDevice device = m_context.getDevice();
1859
1860 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1861 .addSingleBinding(m_bufferLoadDescriptorType, VK_SHADER_STAGE_COMPUTE_BIT)
1862 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1863 .build(vk, device);
1864
1865 m_descriptorPool = DescriptorPoolBuilder()
1866 .addType(m_bufferLoadDescriptorType)
1867 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1868 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1869
1870 VkFormat dstFormat = formatHasThreeComponents(m_format) ? getSingleComponentFormat(m_format) : m_format;
1871
1872 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1873 m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_srcViewOffset, m_imageSizeBytes);
1874 m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), dstFormat, m_dstViewOffset, m_imageSizeBytes);
1875
1876 return *m_descriptorSetLayout; // not passing the ownership
1877 }
1878
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)1879 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1880 {
1881 DE_ASSERT(layerNdx == 0);
1882 DE_UNREF(layerNdx);
1883
1884 const VkDevice device = m_context.getDevice();
1885 const DeviceInterface& vk = m_context.getDeviceInterface();
1886
1887 DescriptorSetUpdateBuilder()
1888 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), m_bufferLoadDescriptorType, &m_bufferViewSrc.get())
1889 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
1890 .update(vk, device);
1891 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1892 }
1893
commandAfterCompute(const VkCommandBuffer cmdBuffer)1894 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1895 {
1896 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes + m_dstViewOffset);
1897 }
1898
createInstance(Context & context) const1899 TestInstance* StoreTest::createInstance (Context& context) const
1900 {
1901 if (m_texture.type() == IMAGE_TYPE_BUFFER)
1902 return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_minalign);
1903 else
1904 return new ImageStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_singleLayerBind, m_minalign);
1905 }
1906
createInstance(Context & context) const1907 TestInstance* LoadStoreTest::createInstance (Context& context) const
1908 {
1909 if (m_imageLoadStoreLodAMD)
1910 return new ImageLoadStoreLodAMDTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
1911
1912 if (m_texture.type() == IMAGE_TYPE_BUFFER)
1913 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_minalign, m_bufferLoadUniform);
1914 else
1915 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
1916 }
1917
1918 class ImageExtendOperandTestInstance : public BaseTestInstance
1919 {
1920 public:
1921 ImageExtendOperandTestInstance (Context& context,
1922 const Texture& texture,
1923 const VkFormat format);
1924
~ImageExtendOperandTestInstance(void)1925 virtual ~ImageExtendOperandTestInstance (void) {};
1926
1927 protected:
1928
1929 VkDescriptorSetLayout prepareDescriptors (void);
1930 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
1931 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
1932 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1933
1934 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1935 const VkPipelineLayout pipelineLayout,
1936 const int layerNdx);
1937
1938 tcu::TestStatus verifyResult (void);
1939
1940 protected:
1941
1942 bool m_isSigned;
1943 tcu::TextureLevel m_inputImageData;
1944
1945 de::MovePtr<Image> m_imageSrc; // source image
1946 SharedVkImageView m_imageSrcView;
1947 VkDeviceSize m_imageSrcSize;
1948
1949 de::MovePtr<Image> m_imageDst; // dest image
1950 SharedVkImageView m_imageDstView;
1951 VkFormat m_imageDstFormat;
1952 VkDeviceSize m_imageDstSize;
1953
1954 de::MovePtr<Buffer> m_buffer; // result buffer
1955
1956 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1957 Move<VkDescriptorPool> m_descriptorPool;
1958 SharedVkDescriptorSet m_descriptorSet;
1959 };
1960
ImageExtendOperandTestInstance(Context & context,const Texture & texture,const VkFormat format)1961 ImageExtendOperandTestInstance::ImageExtendOperandTestInstance (Context& context,
1962 const Texture& texture,
1963 const VkFormat format)
1964 : BaseTestInstance (context, texture, format, true, true, false, false)
1965 {
1966 const DeviceInterface& vk = m_context.getDeviceInterface();
1967 const VkDevice device = m_context.getDevice();
1968 Allocator& allocator = m_context.getDefaultAllocator();
1969 const deInt32 width = texture.size().x();
1970 const deInt32 height = texture.size().y();
1971 const tcu::TextureFormat textureFormat = mapVkFormat(m_format);
1972
1973 // Generate reference image
1974 m_isSigned = (getTextureChannelClass(textureFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
1975 m_inputImageData.setStorage(textureFormat, width, height, 1);
1976 const tcu::PixelBufferAccess access = m_inputImageData.getAccess();
1977 int valueStart = m_isSigned ? -width / 2 : 0;
1978 for (int x = 0; x < width; ++x)
1979 for (int y = 0; y < height; ++y)
1980 {
1981 const tcu::IVec4 color(valueStart + x, valueStart + y, valueStart, valueStart);
1982 access.setPixel(color, x, y);
1983 }
1984
1985 // Create source image
1986 m_imageSrc = de::MovePtr<Image>(new Image(
1987 vk, device, allocator,
1988 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0u),
1989 MemoryRequirement::Any));
1990
1991 // Create destination image
1992 m_imageDstFormat = m_isSigned ? VK_FORMAT_R32G32B32A32_SINT : VK_FORMAT_R32G32B32A32_UINT;
1993 m_imageDst = de::MovePtr<Image>(new Image(
1994 vk, device, allocator,
1995 makeImageCreateInfo(m_texture, m_imageDstFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
1996 MemoryRequirement::Any));
1997
1998 // Compute image and buffer sizes
1999 m_imageSrcSize = width * height * tcu::getPixelSize(textureFormat);
2000 m_imageDstSize = width * height * tcu::getPixelSize(mapVkFormat(m_imageDstFormat));
2001 VkDeviceSize bufferSizeBytes = de::max(m_imageSrcSize, m_imageDstSize);
2002
2003 // Create helper buffer able to store input data and image write result
2004 m_buffer = de::MovePtr<Buffer>(new Buffer(
2005 vk, device, allocator,
2006 makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
2007 MemoryRequirement::HostVisible));
2008
2009 const Allocation& alloc = m_buffer->getAllocation();
2010 deMemcpy(alloc.getHostPtr(), m_inputImageData.getAccess().getDataPtr(), static_cast<size_t>(m_imageSrcSize));
2011 flushAlloc(vk, device, alloc);
2012 }
2013
prepareDescriptors(void)2014 VkDescriptorSetLayout ImageExtendOperandTestInstance::prepareDescriptors (void)
2015 {
2016 const DeviceInterface& vk = m_context.getDeviceInterface();
2017 const VkDevice device = m_context.getDevice();
2018
2019 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2020 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2021 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2022 .build(vk, device);
2023
2024 m_descriptorPool = DescriptorPoolBuilder()
2025 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2026 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2027 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
2028
2029 const VkImageViewType viewType = mapImageViewType(m_texture.type());
2030 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2031
2032 m_descriptorSet = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
2033 m_imageSrcView = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
2034 m_imageDstView = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_imageDstFormat, subresourceRange));
2035
2036 return *m_descriptorSetLayout; // not passing the ownership
2037 }
2038
commandBindDescriptorsForLayer(const VkCommandBuffer cmdBuffer,const VkPipelineLayout pipelineLayout,const int layerNdx)2039 void ImageExtendOperandTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
2040 {
2041 DE_UNREF(layerNdx);
2042
2043 const DeviceInterface& vk = m_context.getDeviceInterface();
2044 const VkDevice device = m_context.getDevice();
2045 const VkDescriptorSet descriptorSet = **m_descriptorSet;
2046
2047 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageSrcView, VK_IMAGE_LAYOUT_GENERAL);
2048 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageDstView, VK_IMAGE_LAYOUT_GENERAL);
2049
2050 typedef DescriptorSetUpdateBuilder::Location DSUBL;
2051 DescriptorSetUpdateBuilder()
2052 .writeSingle(descriptorSet, DSUBL::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
2053 .writeSingle(descriptorSet, DSUBL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
2054 .update(vk, device);
2055 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
2056 }
2057
commandBeforeCompute(const VkCommandBuffer cmdBuffer)2058 void ImageExtendOperandTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
2059 {
2060 const DeviceInterface& vk = m_context.getDeviceInterface();
2061
2062 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
2063 {
2064 const VkImageMemoryBarrier preCopyImageBarriers[] =
2065 {
2066 makeImageMemoryBarrier(
2067 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
2068 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2069 m_imageSrc->get(), fullImageSubresourceRange),
2070 makeImageMemoryBarrier(
2071 0u, VK_ACCESS_SHADER_WRITE_BIT,
2072 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
2073 m_imageDst->get(), fullImageSubresourceRange)
2074 };
2075
2076 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
2077 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2078 m_buffer->get(), 0ull, m_imageSrcSize);
2079
2080 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
2081 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
2082 }
2083 {
2084 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
2085 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
2086 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
2087 m_imageSrc->get(), fullImageSubresourceRange);
2088
2089 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
2090
2091 vk.cmdCopyBufferToImage(cmdBuffer, m_buffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
2092 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);
2093 }
2094 }
2095
commandBetweenShaderInvocations(const VkCommandBuffer cmdBuffer)2096 void ImageExtendOperandTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
2097 {
2098 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
2099 }
2100
commandAfterCompute(const VkCommandBuffer cmdBuffer)2101 void ImageExtendOperandTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
2102 {
2103 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_buffer->get(), m_imageDstSize, m_texture);
2104 }
2105
verifyResult(void)2106 tcu::TestStatus ImageExtendOperandTestInstance::verifyResult (void)
2107 {
2108 const DeviceInterface& vk = m_context.getDeviceInterface();
2109 const VkDevice device = m_context.getDevice();
2110 const tcu::IVec3 imageSize = m_texture.size();
2111 const tcu::PixelBufferAccess inputAccess = m_inputImageData.getAccess();
2112 const deInt32 width = inputAccess.getWidth();
2113 const deInt32 height = inputAccess.getHeight();
2114 tcu::TextureLevel refImage (mapVkFormat(m_imageDstFormat), width, height);
2115 tcu::PixelBufferAccess refAccess = refImage.getAccess();
2116
2117 for (int x = 0; x < width; ++x)
2118 for (int y = 0; y < height; ++y)
2119 {
2120 tcu::IVec4 color = inputAccess.getPixelInt(x, y);
2121 refAccess.setPixel(color, x, y);
2122 }
2123
2124 const Allocation& alloc = m_buffer->getAllocation();
2125 invalidateAlloc(vk, device, alloc);
2126 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageDstFormat), imageSize, alloc.getHostPtr());
2127
2128 if (intThresholdCompare (m_context.getTestContext().getLog(), "Comparison", "Comparison", refAccess, result, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT))
2129 return tcu::TestStatus::pass("Passed");
2130 else
2131 return tcu::TestStatus::fail("Image comparison failed");
2132 }
2133
2134 class ImageExtendOperandTest : public TestCase
2135 {
2136 public:
2137 ImageExtendOperandTest (tcu::TestContext& testCtx,
2138 const std::string& name,
2139 const Texture texture,
2140 const VkFormat format,
2141 const bool signedInt,
2142 const bool relaxedPrecision);
2143
2144 void checkSupport (Context& context) const;
2145 void initPrograms (SourceCollections& programCollection) const;
2146 TestInstance* createInstance (Context& context) const;
2147
2148 private:
2149 const Texture m_texture;
2150 VkFormat m_format;
2151 bool m_operandForce; // Use an operand that doesn't match SampledType?
2152 bool m_relaxedPrecision;
2153 };
2154
ImageExtendOperandTest(tcu::TestContext & testCtx,const std::string & name,const Texture texture,const VkFormat format,const bool operandForce,const bool relaxedPrecision)2155 ImageExtendOperandTest::ImageExtendOperandTest (tcu::TestContext& testCtx,
2156 const std::string& name,
2157 const Texture texture,
2158 const VkFormat format,
2159 const bool operandForce,
2160 const bool relaxedPrecision)
2161 : TestCase (testCtx, name, "")
2162 , m_texture (texture)
2163 , m_format (format)
2164 , m_operandForce (operandForce)
2165 , m_relaxedPrecision (relaxedPrecision)
2166 {
2167 }
2168
checkSupport(Context & context) const2169 void ImageExtendOperandTest::checkSupport (Context& context) const
2170 {
2171 const vk::VkFormatProperties formatProperties (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
2172 context.getPhysicalDevice(),
2173 m_format));
2174
2175 if (!context.requireDeviceFunctionality("VK_KHR_spirv_1_4"))
2176 TCU_THROW(NotSupportedError, "VK_KHR_spirv_1_4 not supported");
2177
2178 if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2179 TCU_THROW(NotSupportedError, "Format not supported for storage images");
2180
2181 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
2182 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
2183 }
2184
initPrograms(SourceCollections & programCollection) const2185 void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection) const
2186 {
2187 tcu::StringTemplate shaderTemplate(
2188 "OpCapability Shader\n"
2189
2190 "${capability}"
2191
2192 "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
2193 "OpMemoryModel Logical GLSL450\n"
2194 "OpEntryPoint GLCompute %main \"main\" %id %src_image_ptr %dst_image_ptr\n"
2195 "OpExecutionMode %main LocalSize 1 1 1\n"
2196
2197 // decorations
2198 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2199
2200 "OpDecorate %src_image_ptr DescriptorSet 0\n"
2201 "OpDecorate %src_image_ptr Binding 0\n"
2202 "OpDecorate %src_image_ptr NonWritable\n"
2203
2204 "${relaxed_precision}"
2205
2206 "OpDecorate %dst_image_ptr DescriptorSet 0\n"
2207 "OpDecorate %dst_image_ptr Binding 1\n"
2208 "OpDecorate %dst_image_ptr NonReadable\n"
2209
2210 // types
2211 "%type_void = OpTypeVoid\n"
2212 "%type_i32 = OpTypeInt 32 1\n"
2213 "%type_u32 = OpTypeInt 32 0\n"
2214 "%type_vec3_i32 = OpTypeVector %type_i32 3\n"
2215 "%type_vec3_u32 = OpTypeVector %type_u32 3\n"
2216 "%type_vec4_i32 = OpTypeVector %type_i32 4\n"
2217 "%type_vec4_u32 = OpTypeVector %type_u32 4\n"
2218
2219 "%type_fun_void = OpTypeFunction %type_void\n"
2220
2221 "${image_types}"
2222
2223 "%type_ptr_in_vec3_u32 = OpTypePointer Input %type_vec3_u32\n"
2224 "%type_ptr_in_u32 = OpTypePointer Input %type_u32\n"
2225
2226 "${image_uniforms}"
2227
2228 // variables
2229 "%id = OpVariable %type_ptr_in_vec3_u32 Input\n"
2230
2231 "${image_variables}"
2232
2233 // main function
2234 "%main = OpFunction %type_void None %type_fun_void\n"
2235 "%label = OpLabel\n"
2236
2237 "${image_load}"
2238
2239 "%coord = OpLoad %type_vec3_u32 %id\n"
2240 "%value = OpImageRead ${read_vect4_type} %src_image %coord ${extend_operand}\n"
2241 " OpImageWrite %dst_image %coord %value ${extend_operand}\n"
2242 " OpReturn\n"
2243 " OpFunctionEnd\n");
2244
2245 tcu::TextureFormat tcuFormat = mapVkFormat(m_format);
2246 const ImageType usedImageType = getImageTypeForSingleLayer(m_texture.type());
2247 const std::string imageTypeStr = getShaderImageType(tcuFormat, usedImageType);
2248 const bool isSigned = (getTextureChannelClass(tcuFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2249
2250 struct FormatData
2251 {
2252 std::string spirvImageFormat;
2253 bool isExtendedFormat;
2254 };
2255 const std::map<vk::VkFormat, FormatData> formatDataMap =
2256 {
2257 // Mandatory support
2258 { VK_FORMAT_R32G32B32A32_UINT, { "Rgba32ui", false } },
2259 { VK_FORMAT_R16G16B16A16_UINT, { "Rgba16ui", false } },
2260 { VK_FORMAT_R8G8B8A8_UINT, { "Rgba8ui", false } },
2261 { VK_FORMAT_R32_UINT, { "R32ui", false } },
2262 { VK_FORMAT_R32G32B32A32_SINT, { "Rgba32i", false } },
2263 { VK_FORMAT_R16G16B16A16_SINT, { "Rgba16i", false } },
2264 { VK_FORMAT_R8G8B8A8_SINT, { "Rgba8i", false } },
2265 { VK_FORMAT_R32_SINT, { "R32i", false } },
2266
2267 // Requires StorageImageExtendedFormats capability
2268 { VK_FORMAT_R32G32_UINT, { "Rg32ui", true } },
2269 { VK_FORMAT_R16G16_UINT, { "Rg16ui", true } },
2270 { VK_FORMAT_R16_UINT, { "R16ui", true } },
2271 { VK_FORMAT_R8G8_UINT, { "Rg8ui", true } },
2272 { VK_FORMAT_R8_UINT, { "R8ui", true } },
2273 { VK_FORMAT_R32G32_SINT, { "Rg32i", true } },
2274 { VK_FORMAT_R16G16_SINT, { "Rg16i", true } },
2275 { VK_FORMAT_R16_SINT, { "R16i", true } },
2276 { VK_FORMAT_R8G8_SINT, { "Rg8i", true } },
2277 { VK_FORMAT_R8_SINT, { "R8i", true } },
2278 { VK_FORMAT_A2B10G10R10_UINT_PACK32, { "Rgb10a2ui", true } }
2279 };
2280
2281 auto it = formatDataMap.find(m_format);
2282 DE_ASSERT (it != formatDataMap.end()); // Missing int format data
2283 auto spirvImageFormat = it->second.spirvImageFormat;
2284
2285 // Request additional capability when needed
2286 std::string capability = "";
2287 if (it->second.isExtendedFormat)
2288 capability += "OpCapability StorageImageExtendedFormats\n";
2289
2290 std::string relaxed = "";
2291 if (m_relaxedPrecision)
2292 relaxed += "OpDecorate %src_image_ptr RelaxedPrecision\n";
2293
2294 // Use i32 SampledType only for signed images and only where we're not forcing
2295 // the signedness usingthe SignExtend operand. Everything else uses u32.
2296 std::string readTypePostfix = (isSigned && !m_operandForce) ? "i32" : "u32";
2297
2298 std::map<std::string, std::string> specializations =
2299 {
2300 { "image_type_id", "%type_image" },
2301 { "image_uni_ptr_type_id", "%type_ptr_uniform_const_image" },
2302 { "image_var_id", "%src_image_ptr" },
2303 { "image_id", "%src_image" },
2304 { "capability", capability },
2305 { "relaxed_precision", relaxed },
2306 { "image_format", spirvImageFormat },
2307 { "sampled_type", (std::string("%type_") + readTypePostfix) },
2308 { "read_vect4_type", (std::string("%type_vec4_") + readTypePostfix) },
2309 { "extend_operand", (isSigned ? "SignExtend" : "ZeroExtend") }
2310 };
2311
2312 // Addidtional parametrization is needed for a case when source and destination textures have same format
2313 tcu::StringTemplate imageTypeTemplate(
2314 "${image_type_id} = OpTypeImage ${sampled_type} 2D 0 0 0 2 ${image_format}\n");
2315 tcu::StringTemplate imageUniformTypeTemplate(
2316 "${image_uni_ptr_type_id} = OpTypePointer UniformConstant ${image_type_id}\n");
2317 tcu::StringTemplate imageVariablesTemplate(
2318 "${image_var_id} = OpVariable ${image_uni_ptr_type_id} UniformConstant\n");
2319 tcu::StringTemplate imageLoadTemplate(
2320 "${image_id} = OpLoad ${image_type_id} ${image_var_id}\n");
2321
2322 std::string imageTypes;
2323 std::string imageUniformTypes;
2324 std::string imageVariables;
2325 std::string imageLoad;
2326
2327 // If input image format is the same as output there is less spir-v definitions
2328 if ((m_format == VK_FORMAT_R32G32B32A32_SINT) || (m_format == VK_FORMAT_R32G32B32A32_UINT))
2329 {
2330 imageTypes = imageTypeTemplate.specialize(specializations);
2331 imageUniformTypes = imageUniformTypeTemplate.specialize(specializations);
2332 imageVariables = imageVariablesTemplate.specialize(specializations);
2333 imageLoad = imageLoadTemplate.specialize(specializations);
2334
2335 specializations["image_var_id"] = "%dst_image_ptr";
2336 specializations["image_id"] = "%dst_image";
2337 imageVariables += imageVariablesTemplate.specialize(specializations);
2338 imageLoad += imageLoadTemplate.specialize(specializations);
2339 }
2340 else
2341 {
2342 specializations["image_type_id"] = "%type_src_image";
2343 specializations["image_uni_ptr_type_id"] = "%type_ptr_uniform_const_src_image";
2344 imageTypes = imageTypeTemplate.specialize(specializations);
2345 imageUniformTypes = imageUniformTypeTemplate.specialize(specializations);
2346 imageVariables = imageVariablesTemplate.specialize(specializations);
2347 imageLoad = imageLoadTemplate.specialize(specializations);
2348
2349 specializations["image_format"] = isSigned ? "Rgba32i" : "Rgba32ui";
2350 specializations["image_type_id"] = "%type_dst_image";
2351 specializations["image_uni_ptr_type_id"] = "%type_ptr_uniform_const_dst_image";
2352 specializations["image_var_id"] = "%dst_image_ptr";
2353 specializations["image_id"] = "%dst_image";
2354 imageTypes += imageTypeTemplate.specialize(specializations);
2355 imageUniformTypes += imageUniformTypeTemplate.specialize(specializations);
2356 imageVariables += imageVariablesTemplate.specialize(specializations);
2357 imageLoad += imageLoadTemplate.specialize(specializations);
2358 }
2359
2360 specializations["image_types"] = imageTypes;
2361 specializations["image_uniforms"] = imageUniformTypes;
2362 specializations["image_variables"] = imageVariables;
2363 specializations["image_load"] = imageLoad;
2364
2365 // Specialize whole shader and add it to program collection
2366 programCollection.spirvAsmSources.add("comp") << shaderTemplate.specialize(specializations)
2367 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
2368 }
2369
createInstance(Context & context) const2370 TestInstance* ImageExtendOperandTest::createInstance(Context& context) const
2371 {
2372 return new ImageExtendOperandTestInstance(context, m_texture, m_format);
2373 }
2374
2375 static const Texture s_textures[] =
2376 {
2377 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1),
2378 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8),
2379 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1),
2380 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8),
2381 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1),
2382 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6),
2383 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2*6),
2384 Texture(IMAGE_TYPE_BUFFER, tcu::IVec3(64, 1, 1), 1),
2385 };
2386
getTestTexture(const ImageType imageType)2387 const Texture& getTestTexture (const ImageType imageType)
2388 {
2389 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2390 if (s_textures[textureNdx].type() == imageType)
2391 return s_textures[textureNdx];
2392
2393 DE_FATAL("Internal error");
2394 return s_textures[0];
2395 }
2396
2397 static const VkFormat s_formats[] =
2398 {
2399 // Mandatory support
2400 VK_FORMAT_R32G32B32A32_SFLOAT,
2401 VK_FORMAT_R16G16B16A16_SFLOAT,
2402 VK_FORMAT_R32_SFLOAT,
2403
2404 VK_FORMAT_R32G32B32A32_UINT,
2405 VK_FORMAT_R16G16B16A16_UINT,
2406 VK_FORMAT_R8G8B8A8_UINT,
2407 VK_FORMAT_R32_UINT,
2408
2409 VK_FORMAT_R32G32B32A32_SINT,
2410 VK_FORMAT_R16G16B16A16_SINT,
2411 VK_FORMAT_R8G8B8A8_SINT,
2412 VK_FORMAT_R32_SINT,
2413
2414 VK_FORMAT_R8G8B8A8_UNORM,
2415
2416 VK_FORMAT_R8G8B8A8_SNORM,
2417
2418 // Requires StorageImageExtendedFormats capability
2419 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2420
2421 VK_FORMAT_R32G32_SFLOAT,
2422 VK_FORMAT_R16G16_SFLOAT,
2423 VK_FORMAT_R16_SFLOAT,
2424
2425 VK_FORMAT_A2B10G10R10_UINT_PACK32,
2426 VK_FORMAT_R32G32_UINT,
2427 VK_FORMAT_R16G16_UINT,
2428 VK_FORMAT_R16_UINT,
2429 VK_FORMAT_R8G8_UINT,
2430 VK_FORMAT_R8_UINT,
2431
2432 VK_FORMAT_R32G32_SINT,
2433 VK_FORMAT_R16G16_SINT,
2434 VK_FORMAT_R16_SINT,
2435 VK_FORMAT_R8G8_SINT,
2436 VK_FORMAT_R8_SINT,
2437
2438 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2439 VK_FORMAT_R16G16B16A16_UNORM,
2440 VK_FORMAT_R16G16B16A16_SNORM,
2441 VK_FORMAT_R16G16_UNORM,
2442 VK_FORMAT_R16_UNORM,
2443 VK_FORMAT_R8G8_UNORM,
2444 VK_FORMAT_R8_UNORM,
2445
2446 VK_FORMAT_R16G16_SNORM,
2447 VK_FORMAT_R16_SNORM,
2448 VK_FORMAT_R8G8_SNORM,
2449 VK_FORMAT_R8_SNORM
2450 };
2451
2452 static const VkFormat s_formatsThreeComponent[] =
2453 {
2454 VK_FORMAT_R8G8B8_UINT,
2455 VK_FORMAT_R8G8B8_SINT,
2456 VK_FORMAT_R8G8B8_UNORM,
2457 VK_FORMAT_R8G8B8_SNORM,
2458 VK_FORMAT_R16G16B16_UINT,
2459 VK_FORMAT_R16G16B16_SINT,
2460 VK_FORMAT_R16G16B16_UNORM,
2461 VK_FORMAT_R16G16B16_SNORM,
2462 VK_FORMAT_R16G16B16_SFLOAT,
2463 VK_FORMAT_R32G32B32_UINT,
2464 VK_FORMAT_R32G32B32_SINT,
2465 VK_FORMAT_R32G32B32_SFLOAT,
2466 };
2467
2468 } // anonymous ns
2469
createImageStoreTests(tcu::TestContext & testCtx)2470 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
2471 {
2472 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
2473 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images"));
2474 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images"));
2475
2476 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2477 {
2478 const Texture& texture = s_textures[textureNdx];
2479 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2480 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2481 const bool isLayered = (texture.numLayers() > 1);
2482
2483 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2484 {
2485 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
2486 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0));
2487
2488 if (isLayered)
2489 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2490 texture, s_formats[formatNdx],
2491 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2492
2493 if (texture.type() == IMAGE_TYPE_BUFFER)
2494 {
2495 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2496 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN));
2497 }
2498 }
2499
2500 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2501 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2502 }
2503
2504 testGroup->addChild(testGroupWithFormat.release());
2505 testGroup->addChild(testGroupWithoutFormat.release());
2506
2507 return testGroup.release();
2508 }
2509
createImageLoadStoreTests(tcu::TestContext & testCtx)2510 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
2511 {
2512 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
2513 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2514 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2515
2516 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2517 {
2518 const Texture& texture = s_textures[textureNdx];
2519 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2520 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2521 const bool isLayered = (texture.numLayers() > 1);
2522
2523 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2524 {
2525 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx]));
2526 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0));
2527
2528 if (isLayered)
2529 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2530 texture, s_formats[formatNdx], s_formats[formatNdx],
2531 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2532 if (texture.type() == IMAGE_TYPE_BUFFER)
2533 {
2534 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));
2535 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));
2536 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN));
2537 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));
2538 }
2539 }
2540
2541 if (texture.type() == IMAGE_TYPE_BUFFER)
2542 {
2543 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formatsThreeComponent); ++formatNdx)
2544 {
2545 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formatsThreeComponent[formatNdx]) + "_uniform", "", texture, s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2546 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));
2547 }
2548 }
2549
2550 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2551 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2552 }
2553
2554 testGroup->addChild(testGroupWithFormat.release());
2555 testGroup->addChild(testGroupWithoutFormat.release());
2556
2557 return testGroup.release();
2558 }
2559
createImageLoadStoreLodAMDTests(tcu::TestContext & testCtx)2560 tcu::TestCaseGroup* createImageLoadStoreLodAMDTests (tcu::TestContext& testCtx)
2561 {
2562 static const Texture textures[] =
2563 {
2564 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8, 1, 6),
2565 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1, 1, 6),
2566 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1, 1, 6),
2567 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8, 1, 6),
2568 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1, 1, 6),
2569 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6, 1, 6),
2570 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2*6, 1, 6),
2571 };
2572
2573 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_lod", "Cases with imageLoad() followed by imageStore()"));
2574 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2575 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2576
2577 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(textures); ++textureNdx)
2578 {
2579 const Texture& texture = textures[textureNdx];
2580 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2581 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2582 const bool isLayered = (texture.numLayers() > 1);
2583
2584 if (texture.type() == IMAGE_TYPE_BUFFER)
2585 continue;
2586
2587 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2588 {
2589 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));
2590 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0, DE_TRUE));
2591
2592 if (isLayered)
2593 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2594 texture, s_formats[formatNdx], s_formats[formatNdx],
2595 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER, DE_TRUE));
2596 }
2597
2598 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2599 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2600 }
2601
2602 testGroup->addChild(testGroupWithFormat.release());
2603 testGroup->addChild(testGroupWithoutFormat.release());
2604
2605 return testGroup.release();
2606 }
2607
createImageFormatReinterpretTests(tcu::TestContext & testCtx)2608 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
2609 {
2610 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats"));
2611
2612 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2613 {
2614 const Texture& texture = s_textures[textureNdx];
2615 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2616
2617 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
2618 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2619 {
2620 const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
2621 if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
2622 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
2623 }
2624 testGroup->addChild(groupByImageViewType.release());
2625 }
2626
2627 return testGroup.release();
2628 }
2629
createImageQualifierRestrictCase(tcu::TestContext & testCtx,const ImageType imageType,const std::string & name)2630 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
2631 {
2632 const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
2633 const Texture& texture = getTestTexture(imageType);
2634 return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2635 }
2636
relaxedOK(VkFormat format)2637 static bool relaxedOK(VkFormat format)
2638 {
2639 tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(format));
2640 int maxBitDepth = deMax32(deMax32(bitDepth[0], bitDepth[1]), deMax32(bitDepth[2], bitDepth[3]));
2641 return maxBitDepth <= 16;
2642 }
2643
createImageExtendOperandsTests(tcu::TestContext & testCtx)2644 tcu::TestCaseGroup* createImageExtendOperandsTests(tcu::TestContext& testCtx)
2645 {
2646 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "extend_operands_spirv1p4", "Cases with SignExtend and ZeroExtend"));
2647
2648 const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
2649 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2650 {
2651 auto format = s_formats[formatNdx];
2652 if (!isIntFormat(format) && !isUintFormat(format))
2653 continue;
2654
2655 for (int prec = 0; prec < 2; prec++)
2656 {
2657 bool relaxedPrecision = (prec != 0);
2658 if (relaxedPrecision && !relaxedOK(format))
2659 continue;
2660
2661 const std::string name = getFormatShortString(format) + (relaxedPrecision ? "_relaxed" : "");
2662 testGroup->addChild(new ImageExtendOperandTest(testCtx, name + "_matching_extend", texture, format, false, relaxedPrecision));
2663 // For signed types test both using the sign bit in SPIR-V and the new operand
2664 if (isIntFormat(format))
2665 testGroup->addChild(new ImageExtendOperandTest(testCtx, name + "_force_sign_extend", texture, format, true, relaxedPrecision));
2666 }
2667 }
2668
2669 return testGroup.release();
2670 }
2671
2672 } // image
2673 } // vkt
2674