1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 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 OpImageWrite tests.
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktImageMismatchedWriteOpTests.hpp"
26
27 #include "vktImageTexture.hpp"
28 #include "vkImageUtil.hpp"
29 #include "vkBuilderUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vktImageTestsUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35
36 #include "tcuStringTemplate.hpp"
37 #include "tcuTexture.hpp"
38 #include "tcuTextureUtil.hpp"
39
40 #include <set>
41
42 #define EPSILON_COMPARE(a,b,e) ((de::max((a),(b))-de::min((a),(b)))<=(e))
43
44 using namespace vk;
45
46 namespace vkt
47 {
48 namespace image
49 {
50 namespace
51 {
52
53 using tcu::TextureFormat;
54 using tcu::StringTemplate;
55 using tcu::TextureChannelClass;
56 using strings = std::map<std::string, std::string>;
57
58 class MismatchedWriteOpTest : public TestCase
59 {
60 public:
61 struct Params
62 {
63 VkFormat vkFormat;
64 int textureWidth;
65 int textureHeight;
66 VkFormat spirvFormat;
67 };
68 typedef de::SharedPtr<Params> ParamsSp;
69
MismatchedWriteOpTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const ParamsSp params)70 MismatchedWriteOpTest (tcu::TestContext& testCtx,
71 const std::string& name,
72 const std::string& description,
73 const ParamsSp params)
74 : TestCase (testCtx, name, description)
75 , m_params (params)
76 {
77 }
78
79 virtual void checkSupport (Context& context) const override;
80 virtual TextureFormat getBufferFormat (void) const;
81 void getProgramCodeAndVariables (StringTemplate& code,
82 strings& variables) const;
83
84 template<class TestParams> void getParams(TestParams&);
85
86 protected:
87 const ParamsSp m_params;
88 };
89
90 class MismatchedVectorSizesTest : public MismatchedWriteOpTest
91 {
92 public:
MismatchedVectorSizesTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const ParamsSp params,const int sourceWidth)93 MismatchedVectorSizesTest (tcu::TestContext& testCtx,
94 const std::string& name,
95 const std::string& description,
96 const ParamsSp params,
97 const int sourceWidth)
98 : MismatchedWriteOpTest (testCtx, name, description, params)
99 , m_sourceWidth (sourceWidth)
100 {
101 DE_ASSERT(getNumUsedChannels(params->vkFormat) <= sourceWidth);
102 }
103
104 virtual void initPrograms (SourceCollections& programCollection) const override;
105 virtual TestInstance* createInstance (Context& context) const override;
106
107 private:
108 const int m_sourceWidth;
109 };
110
111 class MismatchedSignednessAndTypeTest : public MismatchedWriteOpTest
112 {
113 public:
MismatchedSignednessAndTypeTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const ParamsSp params)114 MismatchedSignednessAndTypeTest (tcu::TestContext& testCtx,
115 const std::string& name,
116 const std::string& description,
117 const ParamsSp params)
118 : MismatchedWriteOpTest (testCtx, name, description, params)
119 {
120 }
121
122 virtual void initPrograms (SourceCollections& programCollection) const override;
123 virtual TestInstance* createInstance (Context& context) const override;
124 };
125
126 class MismatchedWriteOpTestInstance : public TestInstance
127 {
128 public:
129 using TestClass = MismatchedWriteOpTest;
130 using ParamsSp = MismatchedWriteOpTest::ParamsSp;
131
MismatchedWriteOpTestInstance(Context & context,const ParamsSp params,const TestClass * test)132 MismatchedWriteOpTestInstance (Context& context,
133 const ParamsSp params,
134 const TestClass* test)
135 : TestInstance (context)
136 , m_params (params)
137 , m_test (test)
138 {
139 }
140
141 virtual tcu::TestStatus iterate (void) override;
142 virtual void clear (tcu::PixelBufferAccess& data) const;
143 virtual void populate (tcu::PixelBufferAccess& data) const;
144 virtual bool compare (tcu::PixelBufferAccess& result,
145 tcu::PixelBufferAccess& reference) const = 0;
146 protected:
147 const ParamsSp m_params;
148 const TestClass* m_test;
149 };
150
151 class MismatchedVectorSizesTestInstance : public MismatchedWriteOpTestInstance
152 {
153 public:
MismatchedVectorSizesTestInstance(Context & context,const ParamsSp params,const TestClass * test)154 MismatchedVectorSizesTestInstance (Context& context,
155 const ParamsSp params,
156 const TestClass* test)
157 : MismatchedWriteOpTestInstance (context, params, test)
158 {
159 }
160
161 bool compare (tcu::PixelBufferAccess& result,
162 tcu::PixelBufferAccess& reference) const override;
163 };
164
165 class MismatchedSignednessAndTypeTestInstance : public MismatchedWriteOpTestInstance
166 {
167 public:
MismatchedSignednessAndTypeTestInstance(Context & context,const ParamsSp params,const TestClass * test)168 MismatchedSignednessAndTypeTestInstance (Context& context,
169 const ParamsSp params,
170 const TestClass* test)
171 : MismatchedWriteOpTestInstance (context, params, test)
172 {
173 }
174
175 bool compare (tcu::PixelBufferAccess& result,
176 tcu::PixelBufferAccess& reference) const override;
177 };
178
179 namespace ut
180 {
181
182 class StorageBuffer2D
183 {
184 public:
185 StorageBuffer2D (Context& context,
186 const tcu::TextureFormat& format,
187 deUint32 width,
188 deUint32 height);
189
getBuffer(void) const190 VkBuffer getBuffer (void) const { return *m_buffer; }
getSize(void) const191 VkDeviceSize getSize (void) const { return m_bufferSize; }
192
getPixelAccess(void)193 tcu::PixelBufferAccess& getPixelAccess (void) { return m_access[0]; }
194
flush(void)195 void flush (void) { flushAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_bufferMemory); }
invalidate(void)196 void invalidate (void) { invalidateAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_bufferMemory); }
197
198 protected:
199 friend class StorageImage2D;
getMemory(void) const200 Allocation& getMemory (void) const { return *m_bufferMemory; }
201
202 private:
203 Context& m_context;
204 const tcu::TextureFormat m_format;
205 const deUint32 m_width;
206 const deUint32 m_height;
207 const VkDeviceSize m_bufferSize;
208 Move<VkBuffer> m_buffer;
209 de::MovePtr<Allocation> m_bufferMemory;
210 std::vector<tcu::PixelBufferAccess> m_access;
211 };
212
213 class StorageImage2D
214 {
215 public:
216 StorageImage2D (Context& context,
217 VkFormat vkFormat,
218 const int width,
219 const int height,
220 bool sparse = false);
221
getView(void) const222 VkImageView getView (void) const { return *m_view; }
223
getPixelAccess(void)224 tcu::PixelBufferAccess& getPixelAccess (void) { return m_buffer.getPixelAccess(); }
225
flush(void)226 void flush (void) { m_buffer.flush(); }
invalidate(void)227 void invalidate (void) { m_buffer.invalidate(); }
228
229 void upload (const VkCommandBuffer cmdBuffer);
230 void download (const VkCommandBuffer cmdBuffer);
231
232 private:
233 Context& m_context;
234 const bool m_sparse;
235 const int m_width;
236 const int m_height;
237 const vk::VkFormat m_vkFormat;
238 const tcu::TextureFormat m_texFormat;
239 StorageBuffer2D m_buffer;
240
241 VkImageLayout m_layout;
242 Move<VkImage> m_image;
243 Move<VkImageView> m_view;
244 Move<VkSemaphore> m_semaphore;
245 std::vector<de::SharedPtr<Allocation>> m_allocations;
246 de::MovePtr<Allocation> m_imageMemory;
247 };
248
StorageImage2D(Context & context,VkFormat vkFormat,const int width,const int height,bool sparse)249 StorageImage2D::StorageImage2D (Context& context, VkFormat vkFormat, const int width, const int height, bool sparse)
250 : m_context (context)
251 , m_sparse (sparse)
252 , m_width (width)
253 , m_height (height)
254 , m_vkFormat (vkFormat)
255 , m_texFormat (mapVkFormat(m_vkFormat))
256 , m_buffer (m_context, m_texFormat, m_width, m_height)
257 {
258 const DeviceInterface& vki = m_context.getDeviceInterface();
259 const VkDevice dev = m_context.getDevice();
260 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
261 Allocator& allocator = m_context.getDefaultAllocator();
262
263 // Create an image
264 {
265 VkImageCreateFlags imageCreateFlags = m_sparse? (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) : 0u;
266 VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
267
268 const VkImageCreateInfo imageCreateInfo =
269 {
270 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
271 DE_NULL, // const void* pNext;
272 imageCreateFlags, // VkImageCreateFlags flags;
273 VK_IMAGE_TYPE_2D, // VkImageType imageType;
274 m_vkFormat, // VkFormat format;
275 { deUint32(m_width), deUint32(m_height), 1u }, // VkExtent3D extent;
276 1u, // deUint32 mipLevels;
277 1u, // deUint32 arrayLayers;
278 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
279 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
280 imageUsageFlags, // VkImageUsageFlags usage;
281 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
282 1u, // deUint32 queueFamilyIndexCount;
283 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
284 (m_layout = VK_IMAGE_LAYOUT_UNDEFINED) // VkImageLayout initialLayout;
285 };
286
287 m_image = createImage(vki, dev, &imageCreateInfo);
288
289 if (m_sparse)
290 {
291 m_semaphore = createSemaphore(vki, dev);
292
293 #ifndef CTS_USES_VULKANSC
294 allocateAndBindSparseImage( vki, dev, m_context.getPhysicalDevice(), m_context.getInstanceInterface(),
295 imageCreateInfo, *m_semaphore, m_context.getSparseQueue(),
296 allocator, m_allocations, mapVkFormat(m_vkFormat), *m_image );
297 #endif // CTS_USES_VULKANSC
298 }
299 else
300 {
301 m_imageMemory = allocator.allocate(getImageMemoryRequirements(vki, dev, *m_image), MemoryRequirement::Any);
302 VK_CHECK(vki.bindImageMemory(dev, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
303 }
304
305 VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
306 m_view = makeImageView(vki, dev, *m_image, VK_IMAGE_VIEW_TYPE_2D, m_vkFormat, subresourceRange);
307 }
308 }
309
upload(const VkCommandBuffer cmdBuffer)310 void StorageImage2D::upload (const VkCommandBuffer cmdBuffer)
311 {
312 const DeviceInterface& vki = m_context.getDeviceInterface();
313 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
314 const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(tcu::IVec3(m_width, m_height, 1)), 1u);
315
316 {
317 const VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(
318 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
319 m_buffer.getBuffer(), 0ull, m_buffer.getSize());
320
321 const VkImageMemoryBarrier beforeCopyBarrier = makeImageMemoryBarrier(
322 (VkAccessFlagBits)0, VK_ACCESS_TRANSFER_WRITE_BIT,
323 m_layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
324 *m_image, fullImageSubresourceRange);
325
326 vki.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
327 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 1, &beforeCopyBarrier);
328 }
329
330 vki.cmdCopyBufferToImage(cmdBuffer, m_buffer.getBuffer(), *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
331
332 {
333 const VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(
334 VK_ACCESS_TRANSFER_READ_BIT, (VkAccessFlags)0,
335 m_buffer.getBuffer(), 0ull, m_buffer.getSize());
336
337 m_layout = VK_IMAGE_LAYOUT_GENERAL;
338 const VkImageMemoryBarrier afterCopyBarrier = makeImageMemoryBarrier(
339 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
340 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_layout,
341 *m_image, fullImageSubresourceRange);
342
343 vki.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
344 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 1, &afterCopyBarrier);
345 }
346 }
347
download(const VkCommandBuffer cmdBuffer)348 void StorageImage2D::download (const VkCommandBuffer cmdBuffer)
349 {
350 const DeviceInterface& vki = m_context.getDeviceInterface();
351 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
352 const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(tcu::IVec3(m_width, m_height, 1)), 1u);
353
354 {
355 const VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(
356 (VkAccessFlags)0, VK_ACCESS_TRANSFER_WRITE_BIT,
357 m_buffer.getBuffer(), 0ull, m_buffer.getSize());
358
359 const VkImageMemoryBarrier beforeCopyBarrier = makeImageMemoryBarrier(
360 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
361 m_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
362 *m_image, fullImageSubresourceRange);
363
364 vki.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
365 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 1, &beforeCopyBarrier);
366 }
367
368 vki.cmdCopyImageToBuffer(cmdBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_buffer.getBuffer(), 1, ©Region);
369
370 {
371 const VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(
372 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
373 m_buffer.getBuffer(), 0ull, m_buffer.getSize());
374
375 const VkImageMemoryBarrier afterCopyBarrier = makeImageMemoryBarrier(
376 VK_ACCESS_TRANSFER_READ_BIT, (VkAccessFlags)0,
377 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_layout,
378 *m_image, fullImageSubresourceRange);
379
380 vki.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
381 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 1, &afterCopyBarrier);
382 }
383
384 }
385
StorageBuffer2D(Context & context,const tcu::TextureFormat & format,deUint32 width,deUint32 height)386 StorageBuffer2D::StorageBuffer2D (Context& context, const tcu::TextureFormat& format, deUint32 width, deUint32 height)
387 : m_context (context)
388 , m_format (format)
389 , m_width (width)
390 , m_height (height)
391 , m_bufferSize (m_width * m_height * m_format.getPixelSize())
392 {
393 const DeviceInterface& vki = m_context.getDeviceInterface();
394 const VkDevice dev = m_context.getDevice();
395 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
396 Allocator& allocator = m_context.getDefaultAllocator();
397
398 const VkBufferUsageFlags bufferUsageFlags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
399
400 const VkBufferCreateInfo bufferCreateInfo =
401 {
402 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
403 DE_NULL, // const void* pNext;
404 0u, // VkBufferCreateFlags flags;
405 m_bufferSize, // VkDeviceSize size;
406 bufferUsageFlags, // VkBufferUsageFlags usage;
407 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
408 1u, // deUint32 queueFamilyIndexCount;
409 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
410 };
411
412 m_buffer = createBuffer(vki, dev, &bufferCreateInfo);
413
414 m_bufferMemory = allocator.allocate(getBufferMemoryRequirements(vki, dev, *m_buffer), MemoryRequirement::HostVisible);
415 VK_CHECK(vki.bindBufferMemory(dev, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset()));
416
417 m_access.emplace_back(m_format, tcu::IVec3(m_width, m_height, 1), m_bufferMemory->getHostPtr());
418 }
419
gluePixels(const tcu::Vec4 & a,const tcu::Vec4 & b,const int pivot)420 tcu::Vec4 gluePixels (const tcu::Vec4& a, const tcu::Vec4& b, const int pivot)
421 {
422 tcu::Vec4 result;
423 for (int i = 0; i < pivot; ++i) result[i] = a[i];
424 for (int i = pivot; i < 4; ++i) result[i] = b[i];
425 return result;
426 }
427
428 template<class T, int N>
comparePixels(const tcu::Vector<T,N> & res,const tcu::Vector<T,N> & ref,const int targetWidth,const T eps={})429 bool comparePixels (const tcu::Vector<T,N>& res, const tcu::Vector<T,N>& ref, const int targetWidth, const T eps = {})
430 {
431 bool ok = true;
432
433 for (int i = 0; ok && i < targetWidth; ++i)
434 {
435 ok &= EPSILON_COMPARE(res[i], ref[i], eps);
436 }
437
438 return ok;
439 }
440
441 } // ut
442
createInstance(Context & context) const443 TestInstance* MismatchedVectorSizesTest::createInstance (Context& context) const
444 {
445 return (new MismatchedVectorSizesTestInstance(context, m_params, this));
446 }
447
createInstance(Context & context) const448 TestInstance* MismatchedSignednessAndTypeTest::createInstance (Context& context) const
449 {
450 return (new MismatchedSignednessAndTypeTestInstance(context, m_params, this));
451 }
452
453 const VkFormat allFormats[] =
454 {
455 VK_FORMAT_R32G32B32A32_SFLOAT,
456 VK_FORMAT_R32G32_SFLOAT,
457 VK_FORMAT_R32_SFLOAT,
458 VK_FORMAT_R16G16B16A16_SFLOAT,
459 VK_FORMAT_R16G16_SFLOAT,
460 VK_FORMAT_R16_SFLOAT,
461 VK_FORMAT_R16G16B16A16_UNORM,
462 VK_FORMAT_R16G16_UNORM,
463 VK_FORMAT_R16_UNORM,
464 VK_FORMAT_R16G16B16A16_SNORM,
465 VK_FORMAT_R16G16_SNORM,
466 VK_FORMAT_R16_SNORM,
467 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
468 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
469 VK_FORMAT_R8G8B8A8_UNORM,
470 VK_FORMAT_R8G8_UNORM,
471 VK_FORMAT_R8_UNORM,
472 VK_FORMAT_R8G8B8A8_SNORM,
473 VK_FORMAT_R8G8_SNORM,
474 VK_FORMAT_R8_SNORM,
475 VK_FORMAT_R32G32B32A32_SINT,
476 VK_FORMAT_R32G32_SINT,
477 VK_FORMAT_R32_SINT,
478 VK_FORMAT_R16G16B16A16_SINT,
479 VK_FORMAT_R16G16_SINT,
480 VK_FORMAT_R16_SINT,
481 VK_FORMAT_R8G8B8A8_SINT,
482 VK_FORMAT_R8G8_SINT,
483 VK_FORMAT_R8_SINT,
484 VK_FORMAT_R32G32B32A32_UINT,
485 VK_FORMAT_R32G32_UINT,
486 VK_FORMAT_R32_UINT,
487 VK_FORMAT_R16G16B16A16_UINT,
488 VK_FORMAT_R16G16_UINT,
489 VK_FORMAT_R16_UINT,
490 VK_FORMAT_A2B10G10R10_UINT_PACK32,
491 VK_FORMAT_R8G8B8A8_UINT,
492 VK_FORMAT_R8G8_UINT,
493 VK_FORMAT_R8_UINT,
494
495 VK_FORMAT_R64_SINT,
496 VK_FORMAT_R64_UINT,
497 };
498
findFormatsByChannelClass(TextureChannelClass channelClass)499 std::vector<VkFormat> findFormatsByChannelClass(TextureChannelClass channelClass)
500 {
501 std::vector<VkFormat> result;
502 for (const VkFormat& f : allFormats)
503 {
504 if (getTextureChannelClass(mapVkFormat(f).type) == channelClass)
505 result.emplace_back(f);
506 }
507 DE_ASSERT(!result.empty());
508 return result;
509 }
510
getChannelStr(const TextureFormat::ChannelType & type)511 const char* getChannelStr (const TextureFormat::ChannelType& type)
512 {
513 switch (type)
514 {
515 case TextureFormat::FLOAT: return "float";
516 case TextureFormat::SIGNED_INT32: return "sint";
517 case TextureFormat::UNSIGNED_INT32: return "uint";
518 case TextureFormat::FLOAT64: return "double";
519 case TextureFormat::SIGNED_INT64: return "slong";
520 case TextureFormat::UNSIGNED_INT64: return "ulong";
521 default: DE_ASSERT(DE_FALSE);
522 }
523
524 return nullptr;
525 }
526
makeChannelType(tcu::TextureChannelClass channelClass,bool doubled)527 TextureFormat::ChannelType makeChannelType (tcu::TextureChannelClass channelClass, bool doubled)
528 {
529 auto channelType = TextureFormat::ChannelType::CHANNELTYPE_LAST;
530 switch (channelClass)
531 {
532 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
533 channelType = doubled ? TextureFormat::ChannelType::SIGNED_INT64 : TextureFormat::ChannelType::SIGNED_INT32;
534 break;
535 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
536 channelType = doubled ? TextureFormat::ChannelType::UNSIGNED_INT64 : TextureFormat::ChannelType::UNSIGNED_INT32;
537 break;
538 default:
539 channelType = doubled ? TextureFormat::ChannelType::FLOAT64 : TextureFormat::ChannelType::FLOAT;
540 }
541 return channelType;
542 }
543
makeBufferFormat(tcu::TextureChannelClass channelClass,bool doubled)544 TextureFormat makeBufferFormat (tcu::TextureChannelClass channelClass, bool doubled)
545 {
546 return TextureFormat(TextureFormat::ChannelOrder::RGBA, makeChannelType(channelClass, doubled));
547 }
548
checkSupport(Context & context) const549 void MismatchedWriteOpTest::checkSupport (Context& context) const
550 {
551 // capabilities that may be used in the shader
552 if (is64BitIntegerFormat(m_params->vkFormat))
553 {
554 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice());
555 if(!deviceFeatures.shaderInt64)
556 {
557 TCU_THROW(NotSupportedError, "Device feature shaderInt64 is not supported");
558 }
559 context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
560 }
561
562 // extensions used statically in the shader
563 context.requireDeviceFunctionality("VK_KHR_variable_pointers");
564 context.requireDeviceFunctionality("VK_KHR_storage_buffer_storage_class");
565
566 VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_params->vkFormat);
567
568 if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
569 {
570 TCU_THROW(NotSupportedError, "Creating storage image with this format is not supported");
571 }
572 }
573
getBufferFormat(void) const574 TextureFormat MismatchedWriteOpTest::getBufferFormat (void) const
575 {
576 const TextureFormat texFormat = mapVkFormat(m_params->vkFormat);
577 return makeBufferFormat(getTextureChannelClass(texFormat.type), is64BitIntegerFormat(m_params->vkFormat));
578 }
579
getProgramCodeAndVariables(StringTemplate & code,strings & variables) const580 void MismatchedWriteOpTest::getProgramCodeAndVariables (StringTemplate& code, strings& variables) const
581 {
582 std::string shaderTemplate(R"(
583
584 OpCapability Shader
585 OpCapability StorageImageExtendedFormats
586
587 ${CAPABILITY_INT64}
588 OpExtension "SPV_KHR_variable_pointers"
589 OpExtension "SPV_KHR_storage_buffer_storage_class"
590 ${EXTENSIONS}
591
592 %std450 = OpExtInstImport "GLSL.std.450"
593 OpMemoryModel Logical GLSL450
594
595 OpEntryPoint GLCompute %main "main" %gid %image %buffer
596 OpExecutionMode %main LocalSize 1 1 1
597
598 OpDecorate %gid BuiltIn GlobalInvocationId
599
600 OpDecorate %image DescriptorSet 0
601 OpDecorate %image Binding 0
602
603 OpDecorate %rta ArrayStride ${ARRAY_STRIDE}
604 OpMemberDecorate %struct 0 Offset 0
605 OpDecorate %struct Block
606 OpDecorate %buffer DescriptorSet 0
607 OpDecorate %buffer Binding 1
608
609 %void = OpTypeVoid
610 %fn_void = OpTypeFunction %void
611
612 ${TYPES_INT64}
613
614 %float = OpTypeFloat 32
615 %sint = OpTypeInt 32 1
616 %uint = OpTypeInt 32 0
617
618 %v4float = OpTypeVector %float 4
619 %v3float = OpTypeVector %float 3
620 %v2float = OpTypeVector %float 2
621
622 %v4sint = OpTypeVector %sint 4
623 %v3sint = OpTypeVector %sint 3
624 %v2sint = OpTypeVector %sint 2
625
626 %v4uint = OpTypeVector %uint 4
627 %v3uint = OpTypeVector %uint 3
628 %v2uint = OpTypeVector %uint 2
629
630 %v3uint_in_ptr = OpTypePointer Input %v3uint
631 %gid = OpVariable %v3uint_in_ptr Input
632
633 %image_type = OpTypeImage %${SAMPLED_TYPE} 2D 0 0 0 2 ${SPIRV_IMAGE_FORMAT}
634 %image_ptr = OpTypePointer UniformConstant %image_type
635 %image = OpVariable %image_ptr UniformConstant
636
637 %image_width = OpConstant %sint ${IMAGE_WIDTH}
638 %image_height = OpConstant %sint ${IMAGE_HEIGHT}
639
640 %rta_offset = OpConstant %uint 0
641 %rta = OpTypeRuntimeArray %v4${SAMPLED_TYPE}
642 %struct = OpTypeStruct %rta
643 %ssbo_ptr = OpTypePointer StorageBuffer %struct
644 %buffer = OpVariable %ssbo_ptr StorageBuffer
645
646 %red_offset = OpConstant %uint 0
647 %green_offset = OpConstant %uint 1
648 %blue_offset = OpConstant %uint 2
649 %alpha_offset = OpConstant %uint 3
650
651 %${SAMPLED_TYPE}_PTR = OpTypePointer StorageBuffer %${SAMPLED_TYPE}
652 %var_sint_ptr = OpTypePointer Function %sint
653
654 ; Entry main procedure
655 %main = OpFunction %void None %fn_void
656 %entry = OpLabel
657
658 %index = OpVariable %var_sint_ptr Function
659
660 ; Transform gl_GlobalInvocationID.xyz to ivec2(gl_GlobalInvocationID.xy)
661 %id = OpLoad %v3uint %gid
662
663 %u_id_x = OpCompositeExtract %uint %id 0
664 %s_id_x = OpBitcast %sint %u_id_x
665
666 %u_id_y = OpCompositeExtract %uint %id 1
667 %s_id_y = OpBitcast %sint %u_id_y
668
669 %id_xy = OpCompositeConstruct %v2sint %s_id_x %s_id_y
670
671 ; Calculate index in buffer
672 %mul = OpIMul %sint %s_id_y %image_width
673 %add = OpIAdd %sint %mul %s_id_x
674 OpStore %index %add
675
676 ; Final image variable used to read from or write to
677 %img = OpLoad %image_type %image
678
679 ; Accessors to buffer components
680 %idx = OpLoad %sint %index
681 %alpha_access = OpAccessChain %${SAMPLED_TYPE}_PTR %buffer %rta_offset %idx %alpha_offset
682 %blue_access = OpAccessChain %${SAMPLED_TYPE}_PTR %buffer %rta_offset %idx %blue_offset
683 %green_access = OpAccessChain %${SAMPLED_TYPE}_PTR %buffer %rta_offset %idx %green_offset
684 %red_access = OpAccessChain %${SAMPLED_TYPE}_PTR %buffer %rta_offset %idx %red_offset
685
686 %red = OpLoad %${SAMPLED_TYPE} %red_access
687 %green = OpLoad %${SAMPLED_TYPE} %green_access
688 %blue = OpLoad %${SAMPLED_TYPE} %blue_access
689 %alpha = OpLoad %${SAMPLED_TYPE} %alpha_access
690
691 ${WRITE_TO_IMAGE}
692
693 OpReturn
694 OpFunctionEnd
695 )");
696
697 const std::string typesInt64(R"(
698 %slong = OpTypeInt 64 1
699 %ulong = OpTypeInt 64 0
700
701 %v4slong = OpTypeVector %slong 4
702 %v3slong = OpTypeVector %slong 3
703 %v2slong = OpTypeVector %slong 2
704
705 %v4ulong = OpTypeVector %ulong 4
706 %v3ulong = OpTypeVector %ulong 3
707 %v2ulong = OpTypeVector %ulong 2
708 )");
709
710 const tcu::TextureFormat buffFormat = getBufferFormat();
711
712 variables["SPIRV_IMAGE_FORMAT"] = getSpirvFormat(m_params->vkFormat);
713 variables["CAPABILITY_INT64"] = "";
714 variables["EXTENSIONS"] = "";
715 variables["TYPES_INT64"] = "";
716
717 if (is64BitIntegerFormat(m_params->vkFormat))
718 {
719 variables["EXTENSIONS"] = "OpExtension \"SPV_EXT_shader_image_int64\"";
720 variables["CAPABILITY_INT64"] = "OpCapability Int64ImageEXT\n"
721 "OpCapability Int64";
722 variables["TYPES_INT64"] = typesInt64;
723 }
724
725 variables["SAMPLED_TYPE"] = getChannelStr(buffFormat.type);
726 variables["IMAGE_WIDTH"] = std::to_string(m_params->textureWidth);
727 variables["IMAGE_HEIGHT"] = std::to_string(m_params->textureHeight);
728 variables["ARRAY_STRIDE"] = std::to_string(tcu::getChannelSize(buffFormat.type) * tcu::getNumUsedChannels(buffFormat.order));
729
730 code.setString(shaderTemplate);
731 }
732
initPrograms(SourceCollections & programCollection) const733 void MismatchedVectorSizesTest::initPrograms (SourceCollections& programCollection) const
734 {
735 strings variables {};
736 StringTemplate shaderTemplate {};
737
738 const StringTemplate writeFromSingleComponent (R"(
739 OpImageWrite %img %id_xy %red
740 )");
741 const StringTemplate writeFromTwoComponents (R"(
742 %rg = OpCompositeConstruct %v2${SAMPLED_TYPE} %red %green
743 OpImageWrite %img %id_xy %rg
744 )");
745
746 const StringTemplate writeFromThreeComponents (R"(
747 %rgb = OpCompositeConstruct %v3${SAMPLED_TYPE} %red %green %blue
748 OpImageWrite %img %id_xy %rgb
749 )");
750 const StringTemplate writeFromFourComponents (R"(
751 %rgba = OpCompositeConstruct %v4${SAMPLED_TYPE} %red %green %blue %alpha
752 OpImageWrite %img %id_xy %rgba
753 )");
754
755 getProgramCodeAndVariables(shaderTemplate, variables);
756
757 variables["WRITE_TO_IMAGE"] = (m_sourceWidth == 1
758 ? writeFromSingleComponent
759 : m_sourceWidth == 2
760 ? writeFromTwoComponents
761 : m_sourceWidth == 3
762 ? writeFromThreeComponents
763 : writeFromFourComponents).specialize(variables);
764 programCollection.spirvAsmSources.add("comp")
765 << shaderTemplate.specialize(variables)
766 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
767 }
768
initPrograms(SourceCollections & programCollection) const769 void MismatchedSignednessAndTypeTest::initPrograms (SourceCollections& programCollection) const
770 {
771 strings variables {};
772 StringTemplate shaderTemplate {};
773
774 const StringTemplate writeToImage (R"(
775 %color = OpCompositeConstruct %v4${SAMPLED_TYPE} %red %green %blue %alpha
776 OpImageWrite %img %id_xy %color
777 )");
778
779 getProgramCodeAndVariables(shaderTemplate, variables);
780
781 variables["WRITE_TO_IMAGE"] = writeToImage.specialize(variables);
782
783 programCollection.spirvAsmSources.add("comp")
784 << shaderTemplate.specialize(variables)
785 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
786 }
787
clear(tcu::PixelBufferAccess & pixels) const788 void MismatchedWriteOpTestInstance::clear (tcu::PixelBufferAccess& pixels) const
789 {
790 const auto channelClass = tcu::getTextureChannelClass(mapVkFormat(m_params->vkFormat).type);
791 switch (channelClass)
792 {
793 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
794 tcu::clear(pixels, tcu::IVec4(-1, -2, -3, -4));
795 break;
796
797 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
798 tcu::clear(pixels, tcu::UVec4(1, 2, 3, 4));
799 break;
800
801 default:
802 tcu::clear(pixels, tcu::Vec4(0.2f, 0.3f, 0.4f, 0.5f));
803 }
804 }
805
populate(tcu::PixelBufferAccess & pixels) const806 void MismatchedWriteOpTestInstance::populate (tcu::PixelBufferAccess& pixels) const
807 {
808 const auto texFormat = mapVkFormat(m_params->vkFormat);
809 const auto bitDepth = tcu::getTextureFormatBitDepth(texFormat);
810 const auto channelClass = tcu::getTextureChannelClass(texFormat.type);
811
812 const tcu::IVec4 signedMinValues (bitDepth[0] ? deIntMinValue32(deMin32(bitDepth[0], 32)) : (-1),
813 bitDepth[1] ? deIntMinValue32(deMin32(bitDepth[1], 32)) : (-1),
814 bitDepth[2] ? deIntMinValue32(deMin32(bitDepth[2], 32)) : (-1),
815 bitDepth[3] ? deIntMinValue32(deMin32(bitDepth[3], 32)) : (-1));
816
817 const tcu::IVec4 signedMaxValues (bitDepth[0] ? deIntMaxValue32(deMin32(bitDepth[0], 32)) : 1,
818 bitDepth[1] ? deIntMaxValue32(deMin32(bitDepth[1], 32)) : 1,
819 bitDepth[2] ? deIntMaxValue32(deMin32(bitDepth[2], 32)) : 1,
820 bitDepth[3] ? deIntMaxValue32(deMin32(bitDepth[3], 32)) : 1);
821
822 const tcu::UVec4 unsignedMinValues (0u);
823
824 const tcu::UVec4 unsignedMaxValues (bitDepth[0] ? deUintMaxValue32(deMin32(bitDepth[0], 32)) : 1u,
825 bitDepth[1] ? deUintMaxValue32(deMin32(bitDepth[1], 32)) : 1u,
826 bitDepth[2] ? deUintMaxValue32(deMin32(bitDepth[2], 32)) : 1u,
827 bitDepth[3] ? deUintMaxValue32(deMin32(bitDepth[3], 32)) : 1u);
828
829 auto nextSigned = [&](tcu::IVec4& color)
830 {
831 color[0] = (static_cast<deInt64>(color[0] + 2) < signedMaxValues[0]) ? (color[0] + 2) : signedMinValues[0];
832 color[1] = (static_cast<deInt64>(color[1] + 3) < signedMaxValues[1]) ? (color[1] + 3) : signedMinValues[1];
833 color[2] = (static_cast<deInt64>(color[2] + 5) < signedMaxValues[2]) ? (color[2] + 5) : signedMinValues[2];
834 color[3] = (static_cast<deInt64>(color[3] + 7) < signedMaxValues[3]) ? (color[3] + 7) : signedMinValues[3];
835 };
836
837 auto nextUnsigned = [&](tcu::UVec4& color)
838 {
839 color[0] = (static_cast<deUint64>(color[0] + 2) < unsignedMaxValues[0]) ? (color[0] + 2) : unsignedMinValues[0];
840 color[1] = (static_cast<deUint64>(color[1] + 3) < unsignedMaxValues[1]) ? (color[1] + 3) : unsignedMinValues[1];
841 color[2] = (static_cast<deUint64>(color[2] + 5) < unsignedMaxValues[2]) ? (color[2] + 5) : unsignedMinValues[2];
842 color[3] = (static_cast<deUint64>(color[3] + 7) < unsignedMaxValues[3]) ? (color[3] + 7) : unsignedMinValues[3];
843 };
844
845 deUint64 floatsData [4];
846 tcu::PixelBufferAccess floatsAccess (texFormat, 1, 1, 1, floatsData);
847 tcu::Vec4 tmpFloats (0.0f);
848
849 const float divider (static_cast<float>(m_params->textureHeight));
850 const tcu::Vec4 ufloatStep (1.0f/(divider*1.0f), 1.0f/(divider*2.0f), 1.0f/(divider*3.0f), 1.0f/(divider*5.0f));
851 const tcu::Vec4 sfloatStep (2.0f/(divider*1.0f), 2.0f/(divider*2.0f), 2.0f/(divider*3.0f), 2.0f/(divider*5.0f));
852
853 tcu::IVec4 signedColor (0);
854 tcu::UVec4 unsignedColor (0u);
855 tcu::Vec4 ufloatColor (0.0f);
856 tcu::Vec4 sfloatColor (-1.0f);
857
858 for (int y = 0; y < m_params->textureHeight; ++y)
859 {
860 for (int x = 0; x < m_params->textureWidth; ++x)
861 {
862 switch (channelClass)
863 {
864 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
865 pixels.setPixel(signedColor, x, y);
866 break;
867
868 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
869 pixels.setPixel(unsignedColor, x, y);
870 break;
871
872 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
873 floatsAccess.setPixel(sfloatColor, 0, 0);
874 tmpFloats = ut::gluePixels(floatsAccess.getPixel(0, 0), sfloatColor, tcu::getNumUsedChannels(texFormat.order));
875 pixels.setPixel(tmpFloats, x, y);
876 break;
877
878 // TEXTURECHANNELCLASS_FLOATING_POINT or
879 // TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
880 default:
881 floatsAccess.setPixel(ufloatColor, 0, 0);
882 tmpFloats = ut::gluePixels(floatsAccess.getPixel(0, 0), ufloatColor, tcu::getNumUsedChannels(texFormat.order));
883 pixels.setPixel(tmpFloats, x, y);
884 break;
885 }
886 }
887
888 nextSigned (signedColor);
889 nextUnsigned (unsignedColor);
890 sfloatColor += sfloatStep;
891 ufloatColor += ufloatStep;
892 }
893 }
894
iterate(void)895 tcu::TestStatus MismatchedWriteOpTestInstance::iterate (void)
896 {
897 const DeviceInterface& vki = m_context.getDeviceInterface();
898 const VkDevice dev = m_context.getDevice();
899 const VkQueue queue = m_context.getUniversalQueue();
900 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
901
902 Move<VkCommandPool> cmdPool = createCommandPool(vki, dev, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
903 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vki, dev, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
904 Move<VkShaderModule> shaderModule = createShaderModule(vki, dev, m_context.getBinaryCollection().get("comp"), 0);
905
906 Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
907 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
908 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
909 .build(vki, dev);
910 Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
911 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
912 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
913 .build(vki, dev, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
914 Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vki, dev, *descriptorPool, *descriptorSetLayout);
915 Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vki, dev, *descriptorSetLayout);
916 Move<VkPipeline> pipeline = makeComputePipeline(vki, dev, *pipelineLayout, *shaderModule);
917
918
919 ut::StorageImage2D image (m_context, m_params->vkFormat, m_params->textureWidth, m_params->textureHeight);
920
921 ut::StorageBuffer2D buffer (m_context, m_test->getBufferFormat(), m_params->textureWidth, m_params->textureHeight);
922
923 VkDescriptorImageInfo inputImageInfo = makeDescriptorImageInfo(DE_NULL, image.getView(), VK_IMAGE_LAYOUT_GENERAL);
924 VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(buffer.getBuffer(), 0u, buffer.getSize());
925
926 DescriptorSetUpdateBuilder builder;
927 builder
928 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &inputImageInfo)
929 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
930 .update(vki, dev);
931
932 populate (buffer.getPixelAccess());
933 clear (image.getPixelAccess());
934
935 beginCommandBuffer(vki, *cmdBuffer);
936 image.upload(*cmdBuffer);
937 vki.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
938 vki.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
939 vki.cmdDispatch(*cmdBuffer, m_params->textureWidth, m_params->textureHeight, 1);
940 image.download(*cmdBuffer);
941 endCommandBuffer(vki, *cmdBuffer);
942
943 image.flush();
944 buffer.flush();
945
946 submitCommandsAndWait(vki, dev, queue, *cmdBuffer);
947
948 image.invalidate();
949 buffer.invalidate();
950
951 return compare(image.getPixelAccess(), buffer.getPixelAccess())
952 ? tcu::TestStatus::pass("")
953 : tcu::TestStatus::fail("Pixel comparison failed");
954 }
955
compare(tcu::PixelBufferAccess & result,tcu::PixelBufferAccess & reference) const956 bool MismatchedVectorSizesTestInstance::compare (tcu::PixelBufferAccess& result, tcu::PixelBufferAccess& reference) const
957 {
958 const tcu::TextureFormat texFormat = mapVkFormat(m_params->vkFormat);
959 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(texFormat.type);
960 const int targetWidth = getNumUsedChannels(texFormat.order);
961
962 bool doContinue = true;
963
964 for (int y = 0; doContinue && y < m_params->textureHeight; ++y)
965 {
966 for (int x = 0; doContinue && x < m_params->textureWidth; ++x)
967 {
968 switch (channelClass)
969 {
970 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
971 doContinue = ut::comparePixels(result.getPixelInt(x,y), reference.getPixelInt(x,y), targetWidth );
972 break;
973 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
974 doContinue = ut::comparePixels(result.getPixelUint(x,y), reference.getPixelUint(x,y), targetWidth );
975 break;
976 default:
977 doContinue = ut::comparePixels(result.getPixel(x,y), reference.getPixel(x,y), targetWidth, 0.0005f);
978 break;
979 }
980 }
981 }
982
983 return doContinue;
984 }
985
compare(tcu::PixelBufferAccess & result,tcu::PixelBufferAccess & reference) const986 bool MismatchedSignednessAndTypeTestInstance::compare (tcu::PixelBufferAccess& result, tcu::PixelBufferAccess& reference) const
987 {
988 DE_UNREF(result);
989 DE_UNREF(reference);
990 return true;
991 }
992
993 } // anonymous
994
createImageWriteOpTests(tcu::TestContext & testCtx)995 tcu::TestCaseGroup* createImageWriteOpTests (tcu::TestContext& testCtx)
996 {
997 std::stringstream ss;
998
999 auto genVectorSizesTestName = [&](const VkFormat& f, const int sourceWidth) -> std::string
1000 {
1001 ss.str(std::string());
1002 ss << de::toLower(getSpirvFormat(f)) << "_from";
1003 if (sourceWidth > 1)
1004 ss << "_vec" << sourceWidth;
1005 else ss << "_scalar";
1006
1007 return ss.str();
1008 };
1009
1010 auto testGroup = new tcu::TestCaseGroup(testCtx, "mismatched_write_op", "Test image OpImageWrite operation in various aspects.");
1011 auto testGroupMismatchedVectorSizes = new tcu::TestCaseGroup(testCtx, "mismatched_vector_sizes", "Case OpImageWrite operation on mismatched vector sizes.");
1012 auto testGroupMismatchedSignedness = new tcu::TestCaseGroup(testCtx, "mismatched_signedness_and_type", "Case OpImageWrite operation on mismatched signedness and values.");
1013
1014 for (const VkFormat& f : allFormats)
1015 {
1016 const auto switchClass = getTextureChannelClass(mapVkFormat(f).type);
1017 auto compatibleFormats = findFormatsByChannelClass(switchClass);
1018
1019 auto end = compatibleFormats.cend();
1020 auto begin = compatibleFormats.cbegin();
1021 for (auto i = begin; i != end; ++i)
1022 {
1023 if (is64BitIntegerFormat(i[0]) || is64BitIntegerFormat(f)) continue;
1024
1025 const std::string testName = de::toLower(getSpirvFormat(i[0])) + "_from_" + de::toLower(getSpirvFormat(f));
1026 auto params = new MismatchedWriteOpTest::Params { f, 12, 8*static_cast<int>(std::distance(begin,i)+1), i[0] };
1027 testGroupMismatchedSignedness->addChild(new MismatchedSignednessAndTypeTest(testCtx, testName, {}, MismatchedVectorSizesTest::ParamsSp(params)));
1028 }
1029
1030 for (int sourceWidth = 4; sourceWidth > 0; --sourceWidth)
1031 {
1032 if (sourceWidth >= getNumUsedChannels(f))
1033 {
1034 auto params = new MismatchedWriteOpTest::Params { f, 12*sourceWidth, 8*(4-sourceWidth+1), f };
1035 testGroupMismatchedVectorSizes->addChild(
1036 new MismatchedVectorSizesTest(testCtx, genVectorSizesTestName(f, sourceWidth), {}, MismatchedVectorSizesTest::ParamsSp(params), sourceWidth));
1037 }
1038 }
1039 }
1040
1041 testGroup->addChild(testGroupMismatchedVectorSizes);
1042 testGroup->addChild(testGroupMismatchedSignedness);
1043
1044 return testGroup;
1045 }
1046
1047 } // image
1048 } // vkt
1049