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