1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 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 Testing writing and reading for mismatched formats
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 #include "vkImageWithMemory.hpp"
44
45 #include "deMath.h"
46 #include "deUniquePtr.hpp"
47 #include "deSharedPtr.hpp"
48 #include "deStringUtil.hpp"
49
50 #include "tcuImageCompare.hpp"
51 #include "tcuTexture.hpp"
52 #include "tcuTextureUtil.hpp"
53 #include "tcuFloat.hpp"
54 #include "tcuStringTemplate.hpp"
55
56 #include <string>
57 #include <vector>
58 #include <map>
59
60 using namespace vk;
61
62 namespace vkt
63 {
64 namespace image
65 {
66 namespace
67 {
68
69 struct FormatInfo
70 {
71 const char* GLSLFormat;
72 int VectorWidth;
73 int BytesPerPixel;
74 tcu::TextureChannelClass ChannelClass;
75 };
76
getFormatInfo(VkFormat format)77 FormatInfo getFormatInfo (VkFormat format)
78 {
79 FormatInfo result;
80
81 const tcu::TextureFormat texFormat = mapVkFormat(format);
82
83 result.VectorWidth = getNumUsedChannels(texFormat.order);
84 result.BytesPerPixel = getPixelSize(texFormat);
85 result.ChannelClass = tcu::getTextureChannelClass(texFormat.type);
86
87 return result;
88 }
89
ChannelClassToImageType(tcu::TextureChannelClass channelClass)90 std::string ChannelClassToImageType (tcu::TextureChannelClass channelClass)
91 {
92 switch (channelClass)
93 {
94 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: return "uimage2D";
95 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: return "iimage2D";
96 default: return "image2D";
97 }
98 }
99
ChannelClassToVecType(tcu::TextureChannelClass channelClass)100 std::string ChannelClassToVecType (tcu::TextureChannelClass channelClass)
101 {
102 switch (channelClass)
103 {
104 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: return "uvec4";
105 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: return "ivec4";
106 default: return "vec4";
107 }
108 }
109
ChannelClassToDefaultVecValue(tcu::TextureChannelClass channelClass)110 std::string ChannelClassToDefaultVecValue (tcu::TextureChannelClass channelClass)
111 {
112 switch (channelClass)
113 {
114 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: return "uvec4(1, 10, 100, 1000)";
115 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: return "ivec4(-1, 2, -1000, 2000)";
116 default: return "vec4(0.25, 0.5, 0.0, 1.0)";
117 }
118 }
119
120 const std::map<std::string, FormatInfo> SpirvFormats {
121 { "Rgba32f", { nullptr, 4, 16, tcu::TEXTURECHANNELCLASS_FLOATING_POINT } },
122 { "Rg32f", { nullptr, 2, 8, tcu::TEXTURECHANNELCLASS_FLOATING_POINT } },
123 { "R32f", { nullptr, 1, 4, tcu::TEXTURECHANNELCLASS_FLOATING_POINT } },
124 { "Rgba16f", { nullptr, 4, 8, tcu::TEXTURECHANNELCLASS_FLOATING_POINT } },
125 { "Rg16f", { nullptr, 2, 4, tcu::TEXTURECHANNELCLASS_FLOATING_POINT } },
126 { "R16f", { nullptr, 1, 2, tcu::TEXTURECHANNELCLASS_FLOATING_POINT } },
127 { "Rgba16", { nullptr, 4, 8, tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT } },
128 { "Rg16", { nullptr, 2, 4, tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT } },
129 { "R16", { nullptr, 1, 2, tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT } },
130 { "Rgba16Snorm", { "rgba16_snorm", 4, 8, tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT } },
131 { "Rg16Snorm", { "rg16_snorm", 2, 4, tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT } },
132 { "R16Snorm", { "r16_snorm", 1, 2, tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT } },
133 { "Rgb10A2", { "rgb10_a2", 4, 4, tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT } },
134 { "R11fG11fB10f", { "r11f_g11f_b10f", 3, 4, tcu::TEXTURECHANNELCLASS_FLOATING_POINT } },
135 { "Rgba8", { nullptr, 4, 4, tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT } },
136 { "Rg8", { nullptr, 2, 2, tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT } },
137 { "R8", { nullptr, 1, 1, tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT } },
138 { "Rgba8Snorm", { "rgba8_snorm", 4, 4, tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT } },
139 { "Rg8Snorm", { "rg8_snorm", 2, 2, tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT } },
140 { "R8Snorm", { "r8_snorm", 1, 1, tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT } },
141 { "Rgba32i", { nullptr, 4, 16, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
142 { "Rg32i", { nullptr, 2, 2, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
143 { "R32i", { nullptr, 1, 1, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
144 { "Rgba16i", { nullptr, 4, 8, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
145 { "Rg16i", { nullptr, 2, 4, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
146 { "R16i", { nullptr, 1, 2, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
147 { "Rgba8i", { nullptr, 4, 4, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
148 { "Rg8i", { nullptr, 2, 2, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
149 { "R8i", { nullptr, 1, 1, tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER } },
150 { "Rgba32ui", { nullptr, 4, 16, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
151 { "Rg32ui", { nullptr, 2, 8, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
152 { "R32ui", { nullptr, 1, 4, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
153 { "Rgba16ui", { nullptr, 4, 8, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
154 { "Rg16ui", { nullptr, 2, 4, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
155 { "R16ui", { nullptr, 1, 2, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
156 { "Rgb10a2ui", { "rgb10_a2ui", 4, 4, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
157 { "Rgba8ui", { nullptr, 4, 4, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
158 { "Rg8ui", { nullptr, 2, 2, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } },
159 { "R8ui", { nullptr, 1, 1, tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER } }
160 };
161
getFormatInfo(const std::string & spirvFormat)162 FormatInfo getFormatInfo (const std::string& spirvFormat)
163 {
164 auto it = SpirvFormats.find(spirvFormat);
165 if (it != SpirvFormats.end()) return it->second;
166 else return {"", 0, 0, tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT};
167 }
168
matching(VkFormat format,const std::string & spirvFormat)169 bool matching (VkFormat format, const std::string& spirvFormat)
170 {
171 try
172 {
173 FormatInfo baseFormat = getFormatInfo(format);
174 FormatInfo shaderFormat = getFormatInfo(spirvFormat);
175
176 return (baseFormat.VectorWidth == shaderFormat.VectorWidth &&
177 baseFormat.BytesPerPixel == shaderFormat.BytesPerPixel &&
178 baseFormat.ChannelClass == shaderFormat.ChannelClass);
179 }
180 catch (const tcu::InternalError&)
181 {
182 return false;
183 }
184 }
185
186 enum class TestType
187 {
188 READ = 0,
189 SPARSE_READ,
190 WRITE
191 };
192
fillImageCreateInfo(VkImageCreateInfo & imageCreateInfo,TestType testType,VkFormat format)193 void fillImageCreateInfo (VkImageCreateInfo& imageCreateInfo, TestType testType, VkFormat format)
194 {
195 const VkImageCreateFlags imageFlags = ((testType == TestType::SPARSE_READ) ? (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) : 0u);
196 const VkImageCreateInfo createInfo =
197 {
198 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
199 nullptr, // const void* pNext;
200 imageFlags, // VkImageCreateFlags flags;
201 VK_IMAGE_TYPE_2D, // VkImageType imageType;
202 format, // VkFormat format;
203 makeExtent3D(8, 8, 1), // VkExtent3D extent;
204 1u, // deUint32 mipLevels;
205 1u, // deUint32 arrayLayers;
206 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
207 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
208 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
209 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
210 0u, // deUint32 queueFamilyIndexCount;
211 nullptr, // const deUint32* pQueueFamilyIndices;
212 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
213 };
214
215 imageCreateInfo = createInfo;
216 }
217
218 class MismatchedFormatTest : public TestCase
219 {
220 public:
221 MismatchedFormatTest (tcu::TestContext& testCtx,
222 const std::string& name,
223 const TestType type,
224 const VkFormat format,
225 const std::string& spirvFormat);
226
227 virtual void checkSupport (Context& context) const;
228 void initPrograms (SourceCollections& programCollection) const;
229 TestInstance* createInstance (Context& context) const;
230
231 private:
232 const TestType m_type;
233 const VkFormat m_format;
234 const std::string m_spirvFormat;
235 };
236
MismatchedFormatTest(tcu::TestContext & testCtx,const std::string & name,const TestType type,const VkFormat format,const std::string & spirvFormat)237 MismatchedFormatTest::MismatchedFormatTest (tcu::TestContext& testCtx,
238 const std::string& name,
239 const TestType type,
240 const VkFormat format,
241 const std::string& spirvFormat)
242 : TestCase (testCtx, name)
243 , m_type (type)
244 , m_format (format)
245 , m_spirvFormat (spirvFormat)
246 {
247 }
248
checkSupport(Context & context) const249 void MismatchedFormatTest::checkSupport (Context& context) const
250 {
251 const auto& vki = context.getInstanceInterface();
252 const auto physicalDevice = context.getPhysicalDevice();
253
254 #ifndef CTS_USES_VULKANSC
255 if (m_type == TestType::SPARSE_READ)
256 {
257 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SPARSE_BINDING);
258
259 if (!getPhysicalDeviceFeatures(vki, physicalDevice).sparseResidencyBuffer)
260 TCU_THROW(NotSupportedError, "Sparse partially resident buffers not supported");
261
262 // Check sparse operations support before creating the image.
263 VkImageCreateInfo imageCreateInfo;
264 fillImageCreateInfo(imageCreateInfo, m_type, m_format);
265
266 if (!checkSparseImageFormatSupport(physicalDevice, vki, imageCreateInfo))
267 {
268 TCU_THROW(NotSupportedError, "The image format does not support sparse operations.");
269 }
270
271 if (!getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice()).shaderResourceResidency)
272 {
273 TCU_THROW(NotSupportedError, "Shader resource residency not supported");
274 }
275 }
276 #endif // CTS_USES_VULKANSC
277
278 VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, m_format);
279
280 if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
281 {
282 TCU_THROW(NotSupportedError, "Creating storage image with this format is not supported");
283 }
284 }
285
initPrograms(SourceCollections & programCollection) const286 void MismatchedFormatTest::initPrograms (SourceCollections& programCollection) const
287 {
288 std::string source;
289
290 if (m_type == TestType::READ)
291 {
292 source = R"(
293 #version 460 core
294
295 layout (${FORMAT}, binding=0) uniform ${IMAGE} inputImage;
296
297 void main()
298 {
299 ${VECT} value = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.xy));
300 }
301 )";
302 }
303 else if (m_type == TestType::WRITE)
304 {
305 source = R"(
306 #version 460 core
307
308 layout (${FORMAT}, binding=0) uniform ${IMAGE} inputImage;
309
310 void main()
311 {
312 imageStore(inputImage, ivec2(gl_GlobalInvocationID.xy), ${VALUE});
313 }
314 )";
315 }
316 else if (m_type == TestType::SPARSE_READ)
317 {
318 source = R"(
319 #version 460 core
320 #extension GL_ARB_sparse_texture2 : require
321
322 layout (${FORMAT}, binding=0) uniform ${IMAGE} inputImage;
323
324 void main()
325 {
326 ${VECT} result;
327 int r = sparseImageLoadARB(inputImage, ivec2(gl_GlobalInvocationID.xy), result);
328 }
329 )";
330 }
331
332 const FormatInfo spirvFormatInfo = getFormatInfo(m_spirvFormat);
333
334 const std::string glslFormat = spirvFormatInfo.GLSLFormat ?
335 spirvFormatInfo.GLSLFormat : de::toLower(m_spirvFormat);
336
337 std::map<std::string, std::string> specializations;
338
339 specializations["FORMAT"] = glslFormat;
340 specializations["VECT"] = ChannelClassToVecType(spirvFormatInfo.ChannelClass);
341 specializations["IMAGE"] = ChannelClassToImageType(spirvFormatInfo.ChannelClass);
342 specializations["VALUE"] = ChannelClassToDefaultVecValue(spirvFormatInfo.ChannelClass);
343
344 programCollection.glslSources.add("comp") << glu::ComputeSource( tcu::StringTemplate{source}.specialize(specializations) );
345 }
346
347 class MismatchedFormatTestInstance : public TestInstance
348 {
349 public:
350 MismatchedFormatTestInstance (Context& context,
351 const TestType type,
352 const VkFormat format,
353 const std::string& spirvFormat);
354
355 tcu::TestStatus iterate (void);
356
357 protected:
358 const TestType m_type;
359 const VkFormat m_format;
360 const std::string m_spirvFormat;
361
362 };
363
MismatchedFormatTestInstance(Context & context,const TestType type,const VkFormat format,const std::string & spirvFormat)364 MismatchedFormatTestInstance::MismatchedFormatTestInstance (Context& context, const TestType type, const VkFormat format, const std::string& spirvFormat)
365 : TestInstance (context)
366 , m_type (type)
367 , m_format (format)
368 , m_spirvFormat (spirvFormat)
369 {
370 }
371
iterate(void)372 tcu::TestStatus MismatchedFormatTestInstance::iterate (void)
373 {
374 const DeviceInterface& vk = m_context.getDeviceInterface();
375 const VkDevice device = m_context.getDevice();
376 const VkQueue queue = m_context.getUniversalQueue();
377 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
378 auto& allocator = m_context.getDefaultAllocator();
379 #ifndef CTS_USES_VULKANSC
380 const auto physicalDevice = m_context.getPhysicalDevice();
381 const auto& instance = m_context.getInstanceInterface();
382 #endif // CTS_USES_VULKANSC
383
384 Move<VkShaderModule> shaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0);
385
386 Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
387 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
388 .build(vk, device);
389 Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
390 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
391 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
392
393 Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
394 Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout.get());
395
396 Move<VkPipeline> pipeline = makeComputePipeline(vk, device, *pipelineLayout, *shaderModule);
397
398 VkImageCreateInfo imageCreateInfo;
399 fillImageCreateInfo(imageCreateInfo, m_type, m_format);
400
401 vk::Move<vk::VkImage> storageImage = createImage(vk, device, &imageCreateInfo);
402 const auto tcuFormat = mapVkFormat(m_format);
403
404 de::MovePtr<vk::Allocation> storageAllocation;
405 vk::Move<vk::VkSemaphore> bindSemaphore;
406 std::vector<de::SharedPtr<Allocation> > allocations;
407
408 if (m_type == TestType::SPARSE_READ)
409 {
410 bindSemaphore = createSemaphore(vk, device);
411 #ifndef CTS_USES_VULKANSC
412 allocateAndBindSparseImage( vk, device, physicalDevice, instance,
413 imageCreateInfo, *bindSemaphore, m_context.getSparseQueue(),
414 allocator, allocations, tcuFormat, *storageImage );
415 #endif // CTS_USES_VULKANSC
416 }
417 else
418 {
419 storageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *storageImage), MemoryRequirement::Any);
420 VK_CHECK(vk.bindImageMemory(device, *storageImage, storageAllocation->getMemory(), storageAllocation->getOffset()));
421 }
422
423 const auto subresourceRange = makeImageSubresourceRange(getImageAspectFlags(tcuFormat), 0u, 1u, 0u, 1u);
424 Move<VkImageView> storageImageView = makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_format, subresourceRange);
425 VkDescriptorImageInfo storageImageInfo = makeDescriptorImageInfo(DE_NULL, *storageImageView, VK_IMAGE_LAYOUT_GENERAL);
426
427 DescriptorSetUpdateBuilder builder;
428 builder
429 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImageInfo)
430 .update(vk, device);
431
432 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
433 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
434
435 const auto layoutBarrier = makeImageMemoryBarrier(0u, (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, *storageImage, subresourceRange);
436
437 beginCommandBuffer(vk, *cmdBuffer);
438 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &layoutBarrier);
439 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
440 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
441 vk.cmdDispatch(*cmdBuffer, 8, 8, 1);
442 endCommandBuffer(vk, *cmdBuffer);
443
444 if (m_type == TestType::SPARSE_READ)
445 {
446 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TRANSFER_BIT };
447 submitCommandsAndWait(vk, device, queue, *cmdBuffer, false, 1u, 1u, &bindSemaphore.get(), stageBits);
448 }
449 else
450 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
451
452 return tcu::TestStatus::pass("Passed");
453 }
454
createInstance(Context & context) const455 TestInstance* MismatchedFormatTest::createInstance (Context& context) const
456 {
457 return new MismatchedFormatTestInstance(context, m_type, m_format, m_spirvFormat);
458 }
459
460 } // anonymous ns
461
createImageMismatchedFormatsTests(tcu::TestContext & testCtx)462 tcu::TestCaseGroup* createImageMismatchedFormatsTests (tcu::TestContext& testCtx)
463 {
464 // Test image load/store operations on mismatched formats
465 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "mismatched_formats"));
466 de::MovePtr<tcu::TestCaseGroup> testGroupOpRead(new tcu::TestCaseGroup(testCtx, "image_read", "perform OpImageRead"));
467 de::MovePtr<tcu::TestCaseGroup> testGroupOpWrite(new tcu::TestCaseGroup(testCtx, "image_write", "perform OpImageWrite"));
468 #ifndef CTS_USES_VULKANSC
469 de::MovePtr<tcu::TestCaseGroup> testGroupOpSparseRead(new tcu::TestCaseGroup(testCtx, "sparse_image_read", "perform OpSparseImageRead"));
470 #endif // CTS_USES_VULKANSC
471
472 for (VkFormat format = VK_FORMAT_R4G4_UNORM_PACK8; format < VK_CORE_FORMAT_LAST; format = static_cast<VkFormat>(format+1))
473 {
474 if (isCompressedFormat(format))
475 continue;
476
477 for (auto& pair : SpirvFormats)
478 {
479 const std::string& spirvFormat = pair.first;
480
481 if (matching(format, spirvFormat))
482 {
483 const std::string enumName = getFormatName(format);
484 const std::string testName = de::toLower( enumName.substr(10) + "_with_" + spirvFormat );
485
486 testGroupOpRead->addChild(new MismatchedFormatTest( testCtx, testName,
487 TestType::READ,
488 format, spirvFormat) );
489
490 testGroupOpWrite->addChild(new MismatchedFormatTest(testCtx, testName,
491 TestType::WRITE,
492 format, spirvFormat) );
493 #ifndef CTS_USES_VULKANSC
494 testGroupOpSparseRead->addChild(new MismatchedFormatTest( testCtx, testName,
495 TestType::SPARSE_READ,
496 format, spirvFormat) );
497 #endif // CTS_USES_VULKANSC
498 }
499 }
500 }
501
502 testGroup->addChild(testGroupOpRead.release());
503 testGroup->addChild(testGroupOpWrite.release());
504 #ifndef CTS_USES_VULKANSC
505 testGroup->addChild(testGroupOpSparseRead.release());
506 #endif // CTS_USES_VULKANSC
507
508 return testGroup.release();
509 }
510
511 } // image
512 } // vkt
513