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