• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Google LLC.
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
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineImage2DViewOf3DTests.hpp"
26 #include "vkPipelineConstructionUtil.hpp"
27 #include "vktTestCase.hpp"
28 #include "vkImageUtil.hpp"
29 #include "vkPrograms.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkBufferWithMemory.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "tcuTexture.hpp"
38 #include "tcuPlatform.hpp"
39 #include "tcuImageCompare.hpp"
40 #include "deMemory.h"
41 
42 #include <sstream>
43 #include <vector>
44 
45 namespace vkt
46 {
47 namespace pipeline
48 {
49 
50 using namespace vk;
51 using de::MovePtr;
52 
53 namespace
54 {
55 enum ImageAccessType {
56 	StorageImage = 0,
57 	Sampler,
58 	CombinedImageSampler
59 };
60 
61 enum TestType {
62 	Compute,
63 	Fragment
64 };
65 
66 struct TestParameters {
67 	tcu::IVec3					imageSize;
68 	uint32_t					mipLevel;
69 	int32_t						layerNdx;
70 	ImageAccessType				imageType;
71 	TestType					testType;
72 	VkFormat					imageFormat;
73 	PipelineConstructionType	pipelineConstructionType;
74 };
75 
computeMipLevelDimension(int32_t baseLevelDimension,uint32_t mipLevel)76 inline int32_t computeMipLevelDimension (int32_t baseLevelDimension, uint32_t mipLevel)
77 {
78 	return de::max(baseLevelDimension >> mipLevel, 1);
79 }
80 
computeMipLevelSize(tcu::IVec3 baseLevelSize,uint32_t mipLevel)81 tcu::IVec3 computeMipLevelSize (tcu::IVec3 baseLevelSize, uint32_t mipLevel)
82 {
83 	int32_t width = computeMipLevelDimension(baseLevelSize.x(), mipLevel);
84 	int32_t height = computeMipLevelDimension(baseLevelSize.y(), mipLevel);
85 	int32_t depth = computeMipLevelDimension(baseLevelSize.z(), mipLevel);
86 	return tcu::IVec3(width, height, depth);
87 }
88 
copyImageLayerToBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer buffer,tcu::IVec2 size,VkAccessFlags srcAccessMask,VkImageLayout oldLayout,deUint32 layerToCopy,uint32_t mipLevel)89 void copyImageLayerToBuffer (const DeviceInterface&		vk,
90 							 VkCommandBuffer			cmdBuffer,
91 							 VkImage					image,
92 							 VkBuffer					buffer,
93 							 tcu::IVec2					size,
94 							 VkAccessFlags				srcAccessMask,
95 							 VkImageLayout				oldLayout,
96 							 deUint32					layerToCopy,
97 							 uint32_t					mipLevel)
98 {
99 	const VkImageSubresourceRange	subresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, 0, 1u);
100 	const VkImageMemoryBarrier		imageBarrier		=
101 	{
102 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType
103 		DE_NULL,									// const void*				pNext
104 		srcAccessMask,								// VkAccessFlags			srcAccessMask
105 		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask
106 		oldLayout,									// VkImageLayout			oldLayout
107 		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout
108 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex
109 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex
110 		image,										// VkImage					image
111 		subresourceRange							// VkImageSubresourceRange	subresourceRange
112 	};
113 
114 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
115 						  0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
116 
117 	const VkImageSubresourceLayers	subresource			=
118 	{
119 		subresourceRange.aspectMask,	// VkImageAspectFlags	aspectMask
120 		mipLevel,						// deUint32				mipLevel
121 		0u,								// deUint32				baseArrayLayer
122 		1u,								// deUint32				layerCount
123 	};
124 
125 	const VkBufferImageCopy			region				=
126 	{
127 		0ull,										// VkDeviceSize					bufferOffset
128 		0u,											// deUint32						bufferRowLength
129 		0u,											// deUint32						bufferImageHeight
130 		subresource,								// VkImageSubresourceLayers		imageSubresource
131 		makeOffset3D(0, 0, (int)layerToCopy),		// VkOffset3D					imageOffset
132 		makeExtent3D(size.x(), size.y(), 1u)		// VkExtent3D					imageExtent
133 	};
134 
135 	vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &region);
136 
137 	const VkBufferMemoryBarrier		bufferBarrier		=
138 	{
139 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType
140 		DE_NULL,									// const void*		pNext
141 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask
142 		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask
143 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex
144 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex
145 		buffer,										// VkBuffer			buffer
146 		0ull,										// VkDeviceSize		offset
147 		VK_WHOLE_SIZE								// VkDeviceSize		size
148 	};
149 
150 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
151 						  0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
152 }
153 
154 // Draws a chess pattern to the given 'layer' (z-dimension) of the 'image'. Other layers will be cleared to white.
fillImage(const tcu::PixelBufferAccess & image,const int layer)155 void fillImage (const tcu::PixelBufferAccess& image, const int layer)
156 {
157 	const tcu::Vec4 clearColor = tcu::Vec4(1); // White clear color.
158 	for (int z = 0; z < image.getSize().z(); ++z)
159 	for (int y = 0; y < image.getSize().y(); ++y)
160 	for (int x = 0; x < image.getSize().x(); ++x)
161 	{
162 		if (z == layer)
163 		{
164 			const float c = (float)((x + y) & 1);
165 			const tcu::Vec4 color = tcu::Vec4(c, c, c, 1.0f);
166 			image.setPixel(color, x, y, z);
167 		}
168 		else
169 		{
170 			image.setPixel(clearColor, x, y, z);
171 		}
172 	}
173 }
174 
175 
176 class Image2DView3DImageInstance : public vkt::TestInstance
177 {
178 public:
Image2DView3DImageInstance(Context & context,const TestParameters testParameters)179 								Image2DView3DImageInstance		(Context&				context,
180 																 const TestParameters	testParameters)
181 								: vkt::TestInstance(context),
182 								  m_testParameters(testParameters)
183 								{}
184 
185 	tcu::TestStatus				iterate							(void);
186 private:
187 	void						runComputePipeline				(const VkDescriptorSet&			descriptorSet,
188 																 const VkDescriptorSetLayout	descriptorSetLayout,
189 																 tcu::IVec3&					testMipLevelSize,
190 																 VkCommandBuffer				cmdBuffer,
191 																 VkImage						image,
192 																 VkBuffer						outputBuffer);
193 
194 	void						runGraphicsPipeline				(const VkDescriptorSet&			descriptorSet,
195 																 const VkDescriptorSetLayout	descriptorSetLayout,
196 																 tcu::IVec3&					testMipLevelSize,
197 																 VkCommandBuffer				cmdBuffer,
198 																 VkImage						image,
199 																 VkBuffer						outputBuffer);
200 	const TestParameters		m_testParameters;
201 };
202 
runComputePipeline(const VkDescriptorSet & descriptorSet,const VkDescriptorSetLayout descriptorSetLayout,tcu::IVec3 & testMipLevelSize,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer outputBuffer)203 void Image2DView3DImageInstance::runComputePipeline (const VkDescriptorSet&			descriptorSet,
204 													 const VkDescriptorSetLayout	descriptorSetLayout,
205 													 tcu::IVec3&					testMipLevelSize,
206 													 VkCommandBuffer				cmdBuffer,
207 													 VkImage						image,
208 													 VkBuffer						outputBuffer)
209 {
210 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
211 	const VkDevice					device				= m_context.getDevice();
212 	const VkQueue					queue				= m_context.getUniversalQueue();
213 	const bool						useSampler			= m_testParameters.imageType != StorageImage;
214 
215 	const Unique<VkShaderModule>	shaderModule		(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u));
216 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device, descriptorSetLayout));
217 	const Unique<VkPipeline>		pipeline			(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
218 
219 	vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
220 	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
221 	vk.cmdDispatch(cmdBuffer, testMipLevelSize.x(), testMipLevelSize.y(), 1u);
222 
223 	// Copy the result image to a buffer.
224 	copyImageLayerToBuffer(vk, cmdBuffer, image, outputBuffer, testMipLevelSize.xy(), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, useSampler ? 0u : m_testParameters.layerNdx, useSampler ? 0u : m_testParameters.mipLevel);
225 
226 	endCommandBuffer(vk, cmdBuffer);
227 
228 	// Wait for completion.
229 	submitCommandsAndWait(vk, device, queue, cmdBuffer);
230 }
231 
runGraphicsPipeline(const VkDescriptorSet & descriptorSet,const VkDescriptorSetLayout descriptorSetLayout,tcu::IVec3 & testMipLevelSize,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer outputBuffer)232 void Image2DView3DImageInstance::runGraphicsPipeline (const VkDescriptorSet&		descriptorSet,
233 													  const VkDescriptorSetLayout	descriptorSetLayout,
234 													  tcu::IVec3&					testMipLevelSize,
235 													  VkCommandBuffer				cmdBuffer,
236 													  VkImage						image,
237 													  VkBuffer						outputBuffer)
238 {
239 	const DeviceInterface&							vk								= m_context.getDeviceInterface();
240 	const VkDevice									device							= m_context.getDevice();
241 	const VkQueue									queue							= m_context.getUniversalQueue();
242 	const bool										useSampler						= m_testParameters.imageType != StorageImage;
243 
244 	const Unique<VkShaderModule>					vertShader						(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
245 	const Unique<VkShaderModule>					fragShader						(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
246 	const Unique<VkPipelineLayout>					pipelineLayout					(makePipelineLayout(vk, device, descriptorSetLayout));
247 	const Move<VkRenderPass>						renderPass						= makeRenderPass(vk, device);
248 	const std::vector<VkViewport>					viewport						= {makeViewport	(m_testParameters.imageSize.x(), m_testParameters.imageSize.y())};
249 	const std::vector<VkRect2D>						scissor							= {makeRect2D	(m_testParameters.imageSize.x(), m_testParameters.imageSize.y())};
250 
251 	const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateCreateInfo	=
252 	{
253 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType
254 		DE_NULL,														// const void*								pNext
255 		0u,																// VkPipelineInputAssemblyStateCreateFlags	flags
256 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,								// VkPrimitiveTopology						topology
257 		VK_FALSE														// VkBool32									primitiveRestartEnable
258 	};
259 
260 	const VkVertexInputBindingDescription			vertexInputBindingDescription		=
261 		{
262 			0u,								// deUint32				binding
263 			sizeof(tcu::Vec4),				// deUint32				stride
264 			VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate
265 		};
266 
267 	const VkVertexInputAttributeDescription			vertexInputAttributeDescription		=
268 		{
269 			0u,								// deUint32		location
270 			0u,								// deUint32		binding
271 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format
272 			0u								// deUint32		offset
273 		};
274 
275 	const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfoDefault	=
276 		{
277 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType								sType
278 			DE_NULL,													// const void*									pNext
279 			(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags		flags
280 			1u,															// deUint32										vertexBindingDescriptionCount
281 			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*		pVertexBindingDescriptions
282 			1u,															// deUint32										vertexAttributeDescriptionCount
283 			&vertexInputAttributeDescription							// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
284 		};
285 
286 	vk::GraphicsPipelineWrapper		graphicsPipeline	(vk, device, m_testParameters.pipelineConstructionType, 0u);
287 	graphicsPipeline.setMonolithicPipelineLayout(*pipelineLayout)
288 			.setDefaultDepthStencilState()
289 			.setDefaultRasterizationState()
290 			.setDefaultMultisampleState()
291 			.setupVertexInputState(&vertexInputStateCreateInfoDefault, &inputAssemblyStateCreateInfo)
292 			.setupPreRasterizationShaderState(viewport,
293 											  scissor,
294 											  *pipelineLayout,
295 											  *renderPass,
296 											  0u,
297 											  *vertShader)
298 			.setupFragmentShaderState(*pipelineLayout, *renderPass, 0u, *fragShader)
299 			.setupFragmentOutputState(*renderPass, 0u)
300 			.buildPipeline();
301 
302 	const Move<VkFramebuffer> framebuffer = makeFramebuffer(vk, device, *renderPass, 0u, DE_NULL, testMipLevelSize.x(), testMipLevelSize.y());
303 
304 	// Create vertex buffer and fill it with full screen quad.
305 	const std::vector<tcu::Vec4> vertexData = {
306 			{-1, -1, 1, 1},
307 			{ 1, -1, 1, 1},
308 			{ 1,  1, 1, 1},
309 			{-1,  1, 1, 1},
310 	};
311 	size_t vertexBufferSize = sizeof(tcu::Vec4) * vertexData.size();
312 	BufferWithMemory vertexBuffer(
313 			vk,
314 			device,
315 			m_context.getDefaultAllocator(),
316 			makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
317 			MemoryRequirement::HostVisible);
318 	deMemcpy(vertexBuffer.getAllocation().getHostPtr(), vertexData.data(), vertexBufferSize);
319 	flushAlloc(vk, device, vertexBuffer.getAllocation());
320 
321 	VkDeviceSize vertexBufferOffset = 0;
322 	vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &*vertexBuffer, &vertexBufferOffset);
323 
324 	vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.getPipeline());
325 	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
326 
327 	beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(testMipLevelSize.xy()));
328 	vk.cmdDraw(cmdBuffer, 4, 1, 0, 0);
329 	endRenderPass(vk, cmdBuffer);
330 
331 	// Copy the result image to a buffer.
332 	copyImageLayerToBuffer(vk, cmdBuffer, image, outputBuffer, testMipLevelSize.xy(), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, useSampler ? 0u : m_testParameters.layerNdx, useSampler ? 0u : m_testParameters.mipLevel);
333 
334 	endCommandBuffer(vk, cmdBuffer);
335 
336 	// Wait for completion.
337 	submitCommandsAndWait(vk, device, queue, cmdBuffer);
338 }
339 
iterate(void)340 tcu::TestStatus Image2DView3DImageInstance::iterate (void)
341 {
342 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
343 	const VkDevice						device				= m_context.getDevice();
344 	const VkQueue						queue				= m_context.getUniversalQueue();
345 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
346 	Allocator&							allocator			= m_context.getDefaultAllocator();
347 	tcu::IVec3							imageSize			= m_testParameters.imageSize;
348 	const bool							useSampler			= m_testParameters.imageType != StorageImage;
349 	const tcu::TextureFormat			textureFormat		= mapVkFormat(m_testParameters.imageFormat);
350 	const uint32_t						mipLevelCount		= 3;
351 
352 	tcu::IVec3							testMipLevelSize	= computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel);
353 	uint32_t							bufferSize			= testMipLevelSize.x() * testMipLevelSize.y() * testMipLevelSize.z() * textureFormat.getPixelSize();
354 	const BufferWithMemory				outputBuffer		(vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
355 
356 	// Input image is used with sampler cases only.
357 	de::MovePtr<BufferWithMemory>		inputImageBuffer;
358 
359 	// Upload the test image data for sampler cases.
360 	if (useSampler)
361 	{
362 		// Initialize the input image's mip level and fill the target layer with a chess pattern, others will be white.
363 		tcu::TextureLevel			inputImageMipLevel	(textureFormat, testMipLevelSize.x(), testMipLevelSize.y(), testMipLevelSize.z());
364 		fillImage(inputImageMipLevel.getAccess(), m_testParameters.layerNdx);
365 
366 		// Create a buffer to upload the image.
367 		const VkBufferCreateInfo	bufferCreateInfo	= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
368 		inputImageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
369 
370 		// Upload target mip level to the input buffer.
371 		deMemcpy(inputImageBuffer->getAllocation().getHostPtr(), inputImageMipLevel.getAccess().getDataPtr(), bufferSize);
372 		flushAlloc(vk, device, inputImageBuffer->getAllocation());
373 	}
374 
375 	// Create the test image: sampled image or storage image, depending on the test type.
376 	const VkImageUsageFlags				usage				= VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
377 																VK_IMAGE_USAGE_TRANSFER_DST_BIT |
378 																(useSampler ? VK_IMAGE_USAGE_SAMPLED_BIT : VK_IMAGE_USAGE_STORAGE_BIT);
379 	const VkImageCreateInfo				imageCreateInfo		=
380 	{
381 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,						// VkStructureType			sType
382 		DE_NULL,													// const void*				pNext
383 		VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT,					// VkImageCreateFlags		flags
384 		VK_IMAGE_TYPE_3D,											// VkImageType				imageType
385 		m_testParameters.imageFormat,								// VkFormat					format
386 		makeExtent3D(imageSize.x(), imageSize.y(), imageSize.z()),	// VkExtent3D				extent
387 		(uint32_t)mipLevelCount,									// uint32_t					mipLevels
388 		1u,															// uint32_t					arrayLayers
389 		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits	samples
390 		VK_IMAGE_TILING_OPTIMAL,									// VkImageTiling			tiling
391 		usage,														// VkImageUsageFlags		usage
392 		VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode			sharingMode
393 		0u,															// uint32_t					queueFamilyIndexCount
394 		DE_NULL,													// const uint32_t*			pQueueFamilyIndices
395 		VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			initialLayout
396 	};
397 	ImageWithMemory						testImage			(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any);
398 
399 	// Make an image view covering one of the mip levels.
400 	const VkImageSubresourceRange		subresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, m_testParameters.mipLevel, 1u, m_testParameters.layerNdx, 1u);
401 	const Unique<VkImageView>			imageView			(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, m_testParameters.imageFormat, subresourceRange));
402 
403 	// resultImage is used in sampler / combined image sampler tests to verify the sampled image.
404 	MovePtr<ImageWithMemory>			resultImage;
405 	Move<VkImageView>					resultImageView;
406 	Move<VkSampler>						sampler;
407 	if (useSampler)
408 	{
409 		const VkImageCreateInfo			resultImageCreateInfo		=
410 		{
411 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType
412 			DE_NULL,														// const void*				pNext
413 			0U,																// VkImageCreateFlags		flags
414 			VK_IMAGE_TYPE_2D,												// VkImageType				imageType
415 			m_testParameters.imageFormat,									// VkFormat					format
416 			makeExtent3D(testMipLevelSize.x(), testMipLevelSize.y(), 1),	// VkExtent3D				extent
417 			1u,																// deUint32					mipLevels
418 			1u,																// deUint32					arrayLayers
419 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits	samples
420 			VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling
421 			VK_IMAGE_USAGE_STORAGE_BIT |
422 				VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
423 				VK_IMAGE_USAGE_TRANSFER_DST_BIT,							// VkImageUsageFlags		usage
424 			VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode
425 			0u,																// deUint32					queueFamilyIndexCount
426 			DE_NULL,														// const deUint32*			pQueueFamilyIndices
427 			VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout			initialLayout
428 		};
429 
430 		resultImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, resultImageCreateInfo, MemoryRequirement::Any));
431 		const VkImageSubresourceRange	resultImgSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
432 		resultImageView = makeImageView(vk, device, **resultImage, VK_IMAGE_VIEW_TYPE_2D, m_testParameters.imageFormat, resultImgSubresourceRange);
433 
434 		const VkSamplerCreateInfo		samplerCreateInfo			=
435 		{
436 			VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType			sType
437 			DE_NULL,									// const void*				pNext
438 			(VkSamplerCreateFlags)0,					// VkSamplerCreateFlags		flags
439 			VK_FILTER_NEAREST,							// VkFilter					magFilter
440 			VK_FILTER_NEAREST,							// VkFilter					minFilter
441 			VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode		mipmapMode
442 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeU
443 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeV
444 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeW
445 			0.0f,										// float					mipLodBias
446 			VK_FALSE,									// VkBool32					anisotropyEnable
447 			1.0f,										// float					maxAnisotropy
448 			VK_FALSE,									// VkBool32					compareEnable
449 			VK_COMPARE_OP_ALWAYS,						// VkCompareOp				compareOp
450 			0.0f,										// float					minLod
451 			1.0f,										// float					maxLod
452 			VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor			borderColor
453 			VK_FALSE,									// VkBool32					unnormalizedCoordinates
454 		};
455 		sampler = createSampler(vk, device, &samplerCreateInfo);
456 	}
457 
458 
459 	// Create the descriptor set.
460 	DescriptorSetLayoutBuilder			descriptorSetLayoutBuilder;
461 	DescriptorPoolBuilder				descriptorPoolBuilder;
462 
463 	VkShaderStageFlags					shaderStage					= m_testParameters.testType == Compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
464 	VkPipelineStageFlags				pipelineStage				= m_testParameters.testType == Compute ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
465 	switch (m_testParameters.imageType)
466 	{
467 	case StorageImage:
468 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage);
469 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
470 		break;
471 	case Sampler:
472 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, shaderStage);
473 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, shaderStage);
474 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage);
475 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
476 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER);
477 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
478 		break;
479 	case CombinedImageSampler:
480 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, shaderStage);
481 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage);
482 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
483 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
484 		break;
485 	default:
486 		TCU_THROW(InternalError, "Unimplemented testImage type.");
487 	}
488 
489 	if (useSampler)
490 	{
491 		// Clear the result image.
492 		clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(), **resultImage, tcu::Vec4(0,0,0,1), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, pipelineStage, 0u, 1u);
493 	}
494 	else
495 	{
496 		// Clear the test image.
497 		clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(), testImage.get(), tcu::Vec4(0,0,0,1), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, pipelineStage, 0u, 1u, 0u, mipLevelCount);
498 	}
499 
500 	// Prepare the command buffer.
501 	const Unique<VkCommandPool>			cmdPool						(makeCommandPool(vk, device, queueFamilyIndex));
502 	const Unique<VkCommandBuffer>		cmdBuffer					(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
503 
504 	// Start recording commands.
505 	beginCommandBuffer(vk, *cmdBuffer);
506 
507 	if (useSampler)
508 	{
509 		// Copy the input image to the target mip level.
510 		std::vector<VkBufferImageCopy> copies;
511 		copies.push_back(makeBufferImageCopy(makeExtent3D(testMipLevelSize), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, m_testParameters.mipLevel, 0, 1)));
512 		copyBufferToImage(vk, *cmdBuffer, **inputImageBuffer, bufferSize, copies, VK_IMAGE_ASPECT_COLOR_BIT, mipLevelCount, 1u, *testImage, VK_IMAGE_LAYOUT_GENERAL, pipelineStage);
513 	}
514 
515 	const Move<VkDescriptorSetLayout>	descriptorSetLayout			(descriptorSetLayoutBuilder.build(vk, device));
516 	const Move<VkDescriptorPool>		descriptorPool				(descriptorPoolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
517 	const Unique<VkDescriptorSet>		descriptorSet				(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
518 	const VkDescriptorImageInfo			testImageDescriptorInfo		= makeDescriptorImageInfo(*sampler, *imageView, VK_IMAGE_LAYOUT_GENERAL);
519 
520 	// Write descriptor update.
521 	{
522 		DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
523 		uint32_t bindingIdx = 0;
524 
525 		switch (m_testParameters.imageType)
526 		{
527 		case StorageImage:
528 			descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &testImageDescriptorInfo);
529 			break;
530 		case Sampler:
531 			descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingIdx++), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &testImageDescriptorInfo);
532 			descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingIdx++), VK_DESCRIPTOR_TYPE_SAMPLER, &testImageDescriptorInfo);
533 			break;
534 		case CombinedImageSampler:
535 			descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingIdx++), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &testImageDescriptorInfo);
536 			break;
537 		}
538 
539 		if (useSampler)
540 		{
541 			const VkDescriptorImageInfo resultImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *resultImageView, VK_IMAGE_LAYOUT_GENERAL);
542 			descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingIdx), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageDescriptorInfo);
543 		}
544 
545 		descriptorSetUpdateBuilder.update(vk, device);
546 	}
547 
548 	if (m_testParameters.testType == Compute)
549 		runComputePipeline(*descriptorSet, *descriptorSetLayout, testMipLevelSize, *cmdBuffer, useSampler ? **resultImage : *testImage, *outputBuffer);
550 	else
551 		runGraphicsPipeline(*descriptorSet, *descriptorSetLayout, testMipLevelSize, *cmdBuffer, useSampler ? **resultImage : *testImage, *outputBuffer);
552 
553 	// Validate the results.
554 	{
555 		// Create a reference image.
556 		// The reference image has always a depth of 1, because it will be compared to the 2D result image (sampler cases) or to a single layer of a 3D image.
557 		tcu::TextureLevel			referenceImage			(textureFormat, testMipLevelSize.x(), testMipLevelSize.y(), 1u);
558 		fillImage(referenceImage.getAccess(), 0u);
559 
560 		const Allocation&			outputBufferAllocation	= outputBuffer.getAllocation();
561 		invalidateAlloc(vk, device, outputBufferAllocation);
562 
563 		const deUint32*				bufferPtr				= static_cast<deUint32*>(outputBufferAllocation.getHostPtr());
564 		tcu::ConstPixelBufferAccess	pixelBufferAccess		(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), testMipLevelSize.x(), testMipLevelSize.y(), 1u, bufferPtr);
565 
566 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Result", "Result comparison", referenceImage, pixelBufferAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
567 			return tcu::TestStatus::fail("Pixel comparison failed.");
568 
569 	}
570 
571 	return tcu::TestStatus::pass("pass");
572 }
573 
574 class ComputeImage2DView3DImageTest : public vkt::TestCase
575 {
576 public:
ComputeImage2DView3DImageTest(tcu::TestContext & testContext,const char * name,const char * description,const TestParameters & testParameters)577 								ComputeImage2DView3DImageTest	(tcu::TestContext&				testContext,
578 																 const char*					name,
579 																 const char*					description,
580 																 const TestParameters&			testParameters)
581 																 : vkt::TestCase (testContext, name, description),
582 																 m_testParameters (testParameters) {}
~ComputeImage2DView3DImageTest(void)583 	virtual						~ComputeImage2DView3DImageTest			(void) {}
584 
585 	virtual void				initPrograms					(SourceCollections&				sourceCollections) const;
586 	virtual void				checkSupport					(Context&						context) const;
587 	virtual TestInstance*		createInstance					(Context&						context) const;
588 private:
589 	const TestParameters		m_testParameters;
590 };
591 
592 
checkSupport(Context & context) const593 void ComputeImage2DView3DImageTest::checkSupport (Context& context) const
594 {
595 	DE_ASSERT(m_testParameters.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
596 
597 	if (!context.isDeviceFunctionalitySupported("VK_EXT_image_2d_view_of_3d"))
598 		TCU_THROW(NotSupportedError, "VK_EXT_image_2d_view_of_3d functionality not supported.");
599 
600 	if (!context.getImage2DViewOf3DFeaturesEXT().image2DViewOf3D)
601 		TCU_THROW(NotSupportedError, "image2DViewOf3D not supported.");
602 
603 	if (m_testParameters.imageType != StorageImage && !context.getImage2DViewOf3DFeaturesEXT().sampler2DViewOf3D)
604 		TCU_THROW(NotSupportedError, "sampler2DViewOf3D not supported.");
605 }
606 
initPrograms(SourceCollections & sourceCollections) const607 void ComputeImage2DView3DImageTest::initPrograms (SourceCollections& sourceCollections) const
608 {
609 	std::ostringstream src;
610 	tcu::IVec3 mipLevelSize = computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel);
611 	if (m_testParameters.imageType == StorageImage)
612 	{
613 		src << "#version 450 core\n"
614 			<< "layout (local_size_x = 1, local_size_y = 1) in;\n"
615 			<< "layout (binding = 0, rgba8) writeonly uniform highp image2D storageImage;\n"
616 			<< "void main (void) {\n"
617 			<< "    ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n"
618 			<< "    float c = float((uv.x + uv.y) & 1);\n"
619 			<< "    vec4 color = vec4(c, c, c, 1.0);\n"
620 			<< "    imageStore(storageImage, uv, color);\n"
621 			<< "}\n";
622 	}
623 	else if (m_testParameters.imageType == Sampler)
624 	{
625 		src << "#version 450 core\n"
626 			<< "layout (local_size_x = 1, local_size_y = 1) in;\n"
627 			<< "layout (set=0, binding = 0) uniform texture2D image;\n"
628 			<< "layout (set=0, binding = 1) uniform sampler samp;\n"
629 			<< "layout (rgba8, set=0, binding = 2) writeonly uniform highp image2D verifyImage;\n"
630 			<< "void main (void) {\n"
631 			<< "    ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n"
632 			<< "    vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / " << mipLevelSize.x() <<".0;\n"
633 			<< "    vec4 color = texture(sampler2D(image, samp), texCoord);\n"
634 			<< "    imageStore(verifyImage, uv, color);\n"
635 			<< "}\n";
636 	}
637 	else if (m_testParameters.imageType == CombinedImageSampler)
638 	{
639 		src << "#version 450 core\n"
640 			<< "layout (local_size_x = 1, local_size_y = 1) in;\n"
641 			<< "layout (binding = 0) uniform sampler2D combinedSampler;\n"
642 			<< "layout (rgba8, set=0, binding=1) writeonly uniform highp image2D verifyImage;\n"
643 			<< "void main (void) {\n"
644 			<< "    ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n"
645 			<< "    vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / " << mipLevelSize.x() <<".0;\n"
646 			<< "    vec4 color = texture(combinedSampler, texCoord);\n"
647 			<< "    imageStore(verifyImage, uv, color);\n"
648 			<< "}\n";
649 	}
650 
651 	sourceCollections.glslSources.add("comp") << glu::ComputeSource(src.str());
652 }
653 
createInstance(Context & context) const654 TestInstance* ComputeImage2DView3DImageTest::createInstance (Context& context) const
655 {
656 	return new Image2DView3DImageInstance(context, m_testParameters);
657 }
658 
659 class FragmentImage2DView3DImageTest : public vkt::TestCase
660 {
661 public:
FragmentImage2DView3DImageTest(tcu::TestContext & testContext,const char * name,const char * description,const TestParameters & testParameters)662 								FragmentImage2DView3DImageTest	(tcu::TestContext&				testContext,
663 																 const char*					name,
664 																 const char*					description,
665 																 const TestParameters&			testParameters)
666 																 : vkt::TestCase (testContext, name, description),
667 																 m_testParameters (testParameters) {}
~FragmentImage2DView3DImageTest(void)668 	virtual						~FragmentImage2DView3DImageTest	(void) {}
669 
670 	virtual void				initPrograms					(SourceCollections&				sourceCollections) const;
671 	virtual void				checkSupport					(Context&						context) const;
672 	virtual TestInstance*		createInstance					(Context&						context) const;
673 private:
674 	const TestParameters		m_testParameters;
675 };
676 
initPrograms(SourceCollections & sourceCollections) const677 void FragmentImage2DView3DImageTest::initPrograms (SourceCollections& sourceCollections) const
678 {
679 	std::stringstream vertShader;
680 	vertShader	<< "#version 450 core\n"
681 				<< "layout(location = 0) in vec4 in_position;\n"
682 				<< "out gl_PerVertex {\n"
683 				<< "    vec4  gl_Position;\n"
684 				<< "    float gl_PointSize;\n"
685 				<< "};\n"
686 				<< "void main() {\n"
687 				<< "    gl_PointSize = 1.0;\n"
688 				<< "    gl_Position  = in_position;\n"
689 				<< "}\n";
690 	sourceCollections.glslSources.add("vert") << glu::VertexSource(vertShader.str());
691 
692 	tcu::IVec3 mipLevelSize = computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel);
693 	std::stringstream fragShader;
694 	if (m_testParameters.imageType == StorageImage)
695 	{
696 		fragShader	<< "#version 450 core\n"
697 					<< "layout(rgba8, set = 0, binding = 0) uniform image2D storageImage;\n"
698 					<< "void main()\n"
699 					<< "{\n"
700 					<< "    ivec2 uv = ivec2(gl_FragCoord.xy);\n"
701 					<< "    float c = float((uv.x + uv.y) & 1);\n"
702 					<< "    vec4 color = vec4(c, c, c, 1.0);\n"
703 					<< "    imageStore(storageImage, uv, color);\n"
704 					<< "}\n";
705 	}
706 
707 	else if (m_testParameters.imageType == Sampler)
708 	{
709 		fragShader	<< "#version 450 core\n"
710 					<< "layout (set = 0, binding = 0) uniform texture2D image;\n"
711 					<< "layout (set = 0, binding = 1) uniform sampler samp;\n"
712 					<< "layout (rgba8, set = 0, binding = 2) uniform image2D verifyImage;\n"
713 					<< "void main (void) {\n"
714 					<< "    ivec2 uv = ivec2(gl_FragCoord.xy);\n"
715 					<< "    vec2 texCoord = gl_FragCoord.xy / " << mipLevelSize.x() <<".0;\n"
716 					<< "    vec4 color = texture(sampler2D(image, samp), texCoord);\n"
717 					<< "    imageStore(verifyImage, uv, color);\n"
718 					<< "}\n";
719 	}
720 	else if (m_testParameters.imageType == CombinedImageSampler)
721 	{
722 		fragShader	<< "#version 450 core\n"
723 					<< "layout (set = 0, binding = 0) uniform sampler2D combinedSampler;\n"
724 					<< "layout (rgba8, set = 0, binding = 1) uniform image2D verifyImage;\n"
725 					<< "void main (void) {\n"
726 					<< "    ivec2 uv = ivec2(gl_FragCoord.xy);\n"
727 					<< "    vec2 texCoord = gl_FragCoord.xy / " << mipLevelSize.x() <<".0;\n"
728 					<< "    vec4 color = texture(combinedSampler, texCoord);\n"
729 					<< "    imageStore(verifyImage, uv, color);\n"
730 					<< "}\n";
731 	}
732 	sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragShader.str());
733 }
734 
checkSupport(Context & context) const735 void FragmentImage2DView3DImageTest::checkSupport (Context& context) const
736 {
737 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_testParameters.pipelineConstructionType);
738 
739 	if (!context.isDeviceFunctionalitySupported("VK_EXT_image_2d_view_of_3d"))
740 		TCU_THROW(NotSupportedError, "VK_EXT_image_2d_view_of_3d functionality not supported.");
741 
742 	if (!context.getImage2DViewOf3DFeaturesEXT().image2DViewOf3D)
743 		TCU_THROW(NotSupportedError, "image2DViewOf3D not supported.");
744 
745 	if (m_testParameters.imageType != StorageImage && !context.getImage2DViewOf3DFeaturesEXT().sampler2DViewOf3D)
746 		TCU_THROW(NotSupportedError, "texture2DViewOf3D not supported.");
747 
748 	if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
749 		TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics not supported");
750 }
751 
createInstance(Context & context) const752 TestInstance* FragmentImage2DView3DImageTest::createInstance (Context& context) const
753 {
754 	return new Image2DView3DImageInstance(context, m_testParameters);
755 }
756 
757 } // anonymous
758 
createImage2DViewOf3DTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)759 tcu::TestCaseGroup* createImage2DViewOf3DTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
760 {
761 	de::MovePtr<tcu::TestCaseGroup> imageTests			(new tcu::TestCaseGroup(testCtx, "image_2d_view_3d_image", "2D view 3D image tests"));
762 	de::MovePtr<tcu::TestCaseGroup>	computeGroup		(new tcu::TestCaseGroup(testCtx, "compute", "Compute shader tests."));
763 	de::MovePtr<tcu::TestCaseGroup>	fragmentGroup		(new tcu::TestCaseGroup(testCtx, "fragment", "Fragment shader tests."));
764 
765 	const struct {
766 		const ImageAccessType	imageType;
767 		const std::string		name;
768 	} imageAccessTypes [] {
769 		{ StorageImage,			"storage" },
770 		{ Sampler,				"sampler" },
771 		{ CombinedImageSampler,	"combined_image_sampler" }
772 	};
773 
774 	const int32_t imageDimension = 64;
775 	for (const auto& imageAccessType : imageAccessTypes)
776 	{
777 		de::MovePtr<tcu::TestCaseGroup>	computeSubGroup		(new tcu::TestCaseGroup(testCtx, imageAccessType.name.c_str(), "Fragment shader tests."));
778 		de::MovePtr<tcu::TestCaseGroup>	fragmentSubGroup	(new tcu::TestCaseGroup(testCtx, imageAccessType.name.c_str(), "Fragment shader tests."));
779 		for (uint32_t mipLevel = 0; mipLevel < 3; mipLevel += 2)
780 		{
781 			// Test the first and the last layer of the mip level.
782 			std::vector<int32_t> layers = { 0, computeMipLevelDimension(imageDimension, mipLevel) -1 };
783 			for (const auto& layer : layers)
784 			{
785 				TestParameters testParameters {
786 						tcu::IVec3(imageDimension),	// IVec3						imageSize
787 						mipLevel,					// uint32_t						mipLevel
788 						layer,						// int32_t						layerNdx
789 						imageAccessType.imageType,	// ImageAccessType				imageType
790 						Fragment,					// TestType						testType
791 						VK_FORMAT_R8G8B8A8_UNORM,	// VkFormat						imageFormat
792 						pipelineConstructionType	// PipelineConstructionType		pipelineConstructionType
793 					};
794 				std::string testName = "mip" + std::to_string(mipLevel) +  "_layer" + std::to_string(layer);
795 				fragmentSubGroup->addChild(new FragmentImage2DView3DImageTest(testCtx, testName.c_str(), "description", testParameters));
796 
797 				if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
798 				{
799 					testParameters.testType = Compute;
800 					computeSubGroup->addChild(new ComputeImage2DView3DImageTest(testCtx, testName.c_str(), "description", testParameters));
801 				}
802 			}
803 		}
804 		computeGroup->addChild(computeSubGroup.release());
805 		fragmentGroup->addChild(fragmentSubGroup.release());
806 	}
807 
808 	imageTests->addChild(computeGroup.release());
809 	imageTests->addChild(fragmentGroup.release());
810 	return imageTests.release();
811 }
812 
813 } // pipeline
814 } // vkt
815