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