• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 std::string&	description,
224 											  const TestType		type,
225 											  const VkFormat		format,
226 											  const std::string&	spirvFormat);
227 
228 	virtual void		checkSupport		(Context&			context) const;
229 	void				initPrograms		(SourceCollections&	programCollection) const;
230 	TestInstance*		createInstance		(Context&			context) const;
231 
232 private:
233 	const TestType		m_type;
234 	const VkFormat		m_format;
235 	const std::string	m_spirvFormat;
236 };
237 
MismatchedFormatTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestType type,const VkFormat format,const std::string & spirvFormat)238 MismatchedFormatTest::MismatchedFormatTest (tcu::TestContext&	testCtx,
239 											const std::string&	name,
240 											const std::string&	description,
241 											const TestType		type,
242 											const VkFormat		format,
243 											const std::string&	spirvFormat)
244 	: TestCase						(testCtx, name, description)
245 	, m_type						(type)
246 	, m_format						(format)
247 	, m_spirvFormat					(spirvFormat)
248 {
249 }
250 
checkSupport(Context & context) const251 void MismatchedFormatTest::checkSupport (Context& context) const
252 {
253 	const auto&	vki				= context.getInstanceInterface();
254 	const auto	physicalDevice	= context.getPhysicalDevice();
255 
256 #ifndef CTS_USES_VULKANSC
257 	if (m_type == TestType::SPARSE_READ)
258 	{
259 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SPARSE_BINDING);
260 
261 		if (!getPhysicalDeviceFeatures(vki, physicalDevice).sparseResidencyBuffer)
262 			TCU_THROW(NotSupportedError, "Sparse partially resident buffers not supported");
263 
264 		// Check sparse operations support before creating the image.
265 		VkImageCreateInfo imageCreateInfo;
266 		fillImageCreateInfo(imageCreateInfo, m_type, m_format);
267 
268 		if (!checkSparseImageFormatSupport(physicalDevice, vki, imageCreateInfo))
269 		{
270 			TCU_THROW(NotSupportedError, "The image format does not support sparse operations.");
271 		}
272 
273 		if (!getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice()).shaderResourceResidency)
274 		{
275 			TCU_THROW(NotSupportedError, "Shader resource residency not supported");
276 		}
277 	}
278 #endif // CTS_USES_VULKANSC
279 
280 	VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, m_format);
281 
282 	if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
283 	{
284 		TCU_THROW(NotSupportedError, "Creating storage image with this format is not supported");
285 	}
286 }
287 
initPrograms(SourceCollections & programCollection) const288 void MismatchedFormatTest::initPrograms (SourceCollections& programCollection) const
289 {
290 	std::string	source;
291 
292 	if (m_type == TestType::READ)
293 	{
294 		source = R"(
295 			#version 460 core
296 
297 			layout (${FORMAT}, binding=0) uniform ${IMAGE} inputImage;
298 
299 			void main()
300 			{
301 				${VECT} value = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.xy));
302 			}
303 		)";
304 	}
305 	else if (m_type == TestType::WRITE)
306 	{
307 		source = R"(
308 			#version 460 core
309 
310 			layout (${FORMAT}, binding=0) uniform ${IMAGE} inputImage;
311 
312 			void main()
313 			{
314 				imageStore(inputImage, ivec2(gl_GlobalInvocationID.xy), ${VALUE});
315 			}
316 		)";
317 	}
318 	else if (m_type == TestType::SPARSE_READ)
319 	{
320 		source = R"(
321 			#version 460 core
322 			#extension GL_ARB_sparse_texture2 : require
323 
324 			layout (${FORMAT}, binding=0) uniform ${IMAGE} inputImage;
325 
326 			void main()
327 			{
328 				${VECT} result;
329 				int r = sparseImageLoadARB(inputImage, ivec2(gl_GlobalInvocationID.xy), result);
330 			}
331 		)";
332 	}
333 
334 	const FormatInfo	spirvFormatInfo		=	getFormatInfo(m_spirvFormat);
335 
336 	const std::string	glslFormat			=	spirvFormatInfo.GLSLFormat ?
337 												spirvFormatInfo.GLSLFormat : de::toLower(m_spirvFormat);
338 
339 	std::map<std::string, std::string>			specializations;
340 
341 	specializations["FORMAT"]				=	glslFormat;
342 	specializations["VECT"]					=	ChannelClassToVecType(spirvFormatInfo.ChannelClass);
343 	specializations["IMAGE"]				=	ChannelClassToImageType(spirvFormatInfo.ChannelClass);
344 	specializations["VALUE"]				=	ChannelClassToDefaultVecValue(spirvFormatInfo.ChannelClass);
345 
346 	programCollection.glslSources.add("comp") << glu::ComputeSource( tcu::StringTemplate{source}.specialize(specializations) );
347 }
348 
349 class MismatchedFormatTestInstance : public TestInstance
350 {
351 public:
352 						MismatchedFormatTestInstance (Context&				context,
353 													  const TestType		type,
354 													  const VkFormat		format,
355 													  const std::string&	spirvFormat);
356 
357 	tcu::TestStatus		iterate					(void);
358 
359 protected:
360 	const TestType		m_type;
361 	const VkFormat		m_format;
362 	const std::string	m_spirvFormat;
363 
364 };
365 
MismatchedFormatTestInstance(Context & context,const TestType type,const VkFormat format,const std::string & spirvFormat)366 MismatchedFormatTestInstance::MismatchedFormatTestInstance (Context& context, const TestType type, const VkFormat format, const std::string& spirvFormat)
367 	: TestInstance		(context)
368 	, m_type			(type)
369 	, m_format			(format)
370 	, m_spirvFormat		(spirvFormat)
371 {
372 }
373 
iterate(void)374 tcu::TestStatus MismatchedFormatTestInstance::iterate (void)
375 {
376 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
377 	const VkDevice					device				= m_context.getDevice();
378 	const VkQueue					queue				= m_context.getUniversalQueue();
379 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
380 	auto&							allocator			= m_context.getDefaultAllocator();
381 #ifndef CTS_USES_VULKANSC
382 	const auto						physicalDevice		= m_context.getPhysicalDevice();
383 	const auto&						instance			= m_context.getInstanceInterface();
384 #endif // CTS_USES_VULKANSC
385 
386 	Move<VkShaderModule>			shaderModule		= createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0);
387 
388 	Move<VkDescriptorSetLayout>		descriptorSetLayout	= DescriptorSetLayoutBuilder()
389 															.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
390 															.build(vk, device);
391 	Move<VkDescriptorPool>			descriptorPool		= DescriptorPoolBuilder()
392 															.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
393 															.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
394 
395 	Move<VkDescriptorSet>			descriptorSet		= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
396 	Move<VkPipelineLayout>			pipelineLayout		= makePipelineLayout(vk, device, descriptorSetLayout.get());
397 
398 	Move<VkPipeline>				pipeline			= makeComputePipeline(vk, device, *pipelineLayout, *shaderModule);
399 
400 	VkImageCreateInfo				imageCreateInfo;
401 	fillImageCreateInfo(imageCreateInfo, m_type, m_format);
402 
403 	vk::Move<vk::VkImage>			storageImage		= createImage(vk, device, &imageCreateInfo);
404 	const auto						tcuFormat			= mapVkFormat(m_format);
405 
406 	de::MovePtr<vk::Allocation>					storageAllocation;
407 	vk::Move<vk::VkSemaphore>					bindSemaphore;
408 	std::vector<de::SharedPtr<Allocation> >		allocations;
409 
410 	if (m_type == TestType::SPARSE_READ)
411 	{
412 		bindSemaphore = createSemaphore(vk, device);
413 #ifndef CTS_USES_VULKANSC
414 		allocateAndBindSparseImage(	vk, device, physicalDevice, instance,
415 									imageCreateInfo, *bindSemaphore, m_context.getSparseQueue(),
416 									allocator, allocations, tcuFormat, *storageImage	);
417 #endif // CTS_USES_VULKANSC
418 	}
419 	else
420 	{
421 		storageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *storageImage), MemoryRequirement::Any);
422 		VK_CHECK(vk.bindImageMemory(device, *storageImage, storageAllocation->getMemory(), storageAllocation->getOffset()));
423 	}
424 
425 	const auto						subresourceRange	= makeImageSubresourceRange(getImageAspectFlags(tcuFormat), 0u, 1u, 0u, 1u);
426 	Move<VkImageView>				storageImageView	= makeImageView(vk, device, *storageImage, VK_IMAGE_VIEW_TYPE_2D, m_format, subresourceRange);
427 	VkDescriptorImageInfo			storageImageInfo	= makeDescriptorImageInfo(DE_NULL, *storageImageView, VK_IMAGE_LAYOUT_GENERAL);
428 
429 	DescriptorSetUpdateBuilder		builder;
430 	builder
431 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImageInfo)
432 		.update(vk, device);
433 
434 	Move<VkCommandPool>				cmdPool				= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
435 	Move<VkCommandBuffer>			cmdBuffer			= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
436 
437 	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);
438 
439 	beginCommandBuffer(vk, *cmdBuffer);
440 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &layoutBarrier);
441 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
442 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
443 		vk.cmdDispatch(*cmdBuffer, 8, 8, 1);
444 	endCommandBuffer(vk, *cmdBuffer);
445 
446 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
447 
448 	return tcu::TestStatus::pass("Passed");
449 }
450 
createInstance(Context & context) const451 TestInstance* MismatchedFormatTest::createInstance (Context& context) const
452 {
453 	return new MismatchedFormatTestInstance(context, m_type, m_format, m_spirvFormat);
454 }
455 
456 } // anonymous ns
457 
createImageMismatchedFormatsTests(tcu::TestContext & testCtx)458 tcu::TestCaseGroup* createImageMismatchedFormatsTests (tcu::TestContext& testCtx)
459 {
460 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "mismatched_formats", "Test image load/store operations on mismatched formats"));
461 	de::MovePtr<tcu::TestCaseGroup> testGroupOpRead(new tcu::TestCaseGroup(testCtx, "image_read", "perform OpImageRead"));
462 	de::MovePtr<tcu::TestCaseGroup> testGroupOpWrite(new tcu::TestCaseGroup(testCtx, "image_write", "perform OpImageWrite"));
463 #ifndef CTS_USES_VULKANSC
464 	de::MovePtr<tcu::TestCaseGroup> testGroupOpSparseRead(new tcu::TestCaseGroup(testCtx, "sparse_image_read", "perform OpSparseImageRead"));
465 #endif // CTS_USES_VULKANSC
466 
467 	for (VkFormat format = VK_FORMAT_R4G4_UNORM_PACK8; format < VK_CORE_FORMAT_LAST; format = static_cast<VkFormat>(format+1))
468 	{
469 		for (auto& pair : SpirvFormats)
470 		{
471 			const std::string&	spirvFormat = pair.first;
472 
473 			if (matching(format, spirvFormat))
474 			{
475 				const std::string	enumName	= getFormatName(format);
476 				const std::string	testName	= de::toLower( enumName.substr(10) + "_with_" + spirvFormat );
477 
478 				testGroupOpRead->addChild(new MismatchedFormatTest(	testCtx, testName, "",
479 																	TestType::READ,
480 																	format, spirvFormat) );
481 
482 				testGroupOpWrite->addChild(new MismatchedFormatTest(testCtx, testName, "",
483 																	TestType::WRITE,
484 																	format, spirvFormat) );
485 #ifndef CTS_USES_VULKANSC
486 				testGroupOpSparseRead->addChild(new MismatchedFormatTest(	testCtx, testName, "",
487 																			TestType::SPARSE_READ,
488 																			format, spirvFormat) );
489 #endif // CTS_USES_VULKANSC
490 			}
491 		}
492 	}
493 
494 	testGroup->addChild(testGroupOpRead.release());
495 	testGroup->addChild(testGroupOpWrite.release());
496 #ifndef CTS_USES_VULKANSC
497 	testGroup->addChild(testGroupOpSparseRead.release());
498 #endif // CTS_USES_VULKANSC
499 
500 	return testGroup.release();
501 }
502 
503 } // image
504 } // vkt
505