1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file vktPipelineRenderToImageTests.cpp
21 * \brief Render to image tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktPipelineRenderToImageTests.hpp"
25#include "vktPipelineMakeUtil.hpp"
26#include "vktTestCase.hpp"
27#include "vktTestCaseUtil.hpp"
28#include "vktPipelineVertexUtil.hpp"
29#include "vktTestGroupUtil.hpp"
30
31#include "vkMemUtil.hpp"
32#include "vkQueryUtil.hpp"
33#include "vkTypeUtil.hpp"
34#include "vkRefUtil.hpp"
35#include "vkBuilderUtil.hpp"
36#include "vkPrograms.hpp"
37#include "vkImageUtil.hpp"
38
39#include "tcuTextureUtil.hpp"
40#include "tcuImageCompare.hpp"
41
42#include "deUniquePtr.hpp"
43#include "deSharedPtr.hpp"
44
45#include <string>
46#include <vector>
47
48namespace vkt
49{
50namespace pipeline
51{
52namespace
53{
54using namespace vk;
55using de::UniquePtr;
56using de::MovePtr;
57using de::SharedPtr;
58using tcu::IVec3;
59using tcu::Vec4;
60using tcu::UVec4;
61using tcu::IVec4;
62using std::vector;
63
64typedef SharedPtr<Unique<VkImageView> >	SharedPtrVkImageView;
65typedef SharedPtr<Unique<VkPipeline> >	SharedPtrVkPipeline;
66
67enum Constants
68{
69	REFERENCE_COLOR_VALUE = 125
70};
71
72struct CaseDef
73{
74	VkImageViewType	imageType;
75	IVec3			renderSize;
76	int				numLayers;
77	VkFormat		colorFormat;
78};
79
80template<typename T>
81inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
82{
83	return SharedPtr<Unique<T> >(new Unique<T>(move));
84}
85
86template<typename T>
87inline VkDeviceSize sizeInBytes (const vector<T>& vec)
88{
89	return vec.size() * sizeof(vec[0]);
90}
91
92Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
93									   const VkDevice				device,
94									   const VkPipelineLayout		pipelineLayout,
95									   const VkRenderPass			renderPass,
96									   const VkShaderModule			vertexModule,
97									   const VkShaderModule			fragmentModule,
98									   const IVec3					renderSize,
99									   const VkPrimitiveTopology	topology,
100									   const deUint32				subpass)
101{
102	const VkVertexInputBindingDescription vertexInputBindingDescription =
103	{
104		0u,								// uint32_t				binding;
105		sizeof(Vertex4RGBA),			// uint32_t				stride;
106		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
107	};
108
109	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
110	{
111		{
112			0u,								// uint32_t			location;
113			0u,								// uint32_t			binding;
114			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat			format;
115			0u,								// uint32_t			offset;
116		},
117		{
118			1u,								// uint32_t			location;
119			0u,								// uint32_t			binding;
120			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat			format;
121			sizeof(Vec4),					// uint32_t			offset;
122		}
123	};
124
125	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
126	{
127		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
128		DE_NULL,													// const void*								pNext;
129		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags	flags;
130		1u,															// uint32_t									vertexBindingDescriptionCount;
131		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
132		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),		// uint32_t									vertexAttributeDescriptionCount;
133		vertexInputAttributeDescriptions,							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
134	};
135
136	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
137	{
138		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
139		DE_NULL,														// const void*								pNext;
140		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
141		topology,														// VkPrimitiveTopology						topology;
142		VK_FALSE,														// VkBool32									primitiveRestartEnable;
143	};
144
145	const VkViewport viewport = makeViewport(
146		0.0f, 0.0f,
147		static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
148		0.0f, 1.0f);
149
150	const VkRect2D scissor =
151	{
152		makeOffset2D(0, 0),
153		makeExtent2D(renderSize.x(), renderSize.y()),
154	};
155
156	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
157	{
158		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType						sType;
159		DE_NULL,												// const void*							pNext;
160		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags	flags;
161		1u,														// uint32_t								viewportCount;
162		&viewport,												// const VkViewport*					pViewports;
163		1u,														// uint32_t								scissorCount;
164		&scissor,												// const VkRect2D*						pScissors;
165	};
166
167	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
168	{
169		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
170		DE_NULL,													// const void*								pNext;
171		(VkPipelineRasterizationStateCreateFlags)0,					// VkPipelineRasterizationStateCreateFlags	flags;
172		VK_FALSE,													// VkBool32									depthClampEnable;
173		VK_FALSE,													// VkBool32									rasterizerDiscardEnable;
174		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode;
175		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode;
176		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
177		VK_FALSE,													// VkBool32									depthBiasEnable;
178		0.0f,														// float									depthBiasConstantFactor;
179		0.0f,														// float									depthBiasClamp;
180		0.0f,														// float									depthBiasSlopeFactor;
181		1.0f,														// float									lineWidth;
182	};
183
184	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
185	{
186		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
187		DE_NULL,													// const void*								pNext;
188		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
189		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
190		VK_FALSE,													// VkBool32									sampleShadingEnable;
191		0.0f,														// float									minSampleShading;
192		DE_NULL,													// const VkSampleMask*						pSampleMask;
193		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
194		VK_FALSE													// VkBool32									alphaToOneEnable;
195	};
196
197	const VkStencilOpState stencilOpState = makeStencilOpState(
198		VK_STENCIL_OP_KEEP,		// stencil fail
199		VK_STENCIL_OP_KEEP,		// depth & stencil pass
200		VK_STENCIL_OP_KEEP,		// depth only fail
201		VK_COMPARE_OP_ALWAYS,	// compare op
202		0u,						// compare mask
203		0u,						// write mask
204		0u);					// reference
205
206	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
207	{
208		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
209		DE_NULL,													// const void*								pNext;
210		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
211		VK_FALSE,													// VkBool32									depthTestEnable;
212		VK_FALSE,													// VkBool32									depthWriteEnable;
213		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
214		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
215		VK_FALSE,													// VkBool32									stencilTestEnable;
216		stencilOpState,												// VkStencilOpState							front;
217		stencilOpState,												// VkStencilOpState							back;
218		0.0f,														// float									minDepthBounds;
219		1.0f,														// float									maxDepthBounds;
220	};
221
222	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
223	// Number of blend attachments must equal the number of color attachments during any subpass.
224	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
225	{
226		VK_FALSE,				// VkBool32					blendEnable;
227		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcColorBlendFactor;
228		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstColorBlendFactor;
229		VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp;
230		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcAlphaBlendFactor;
231		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstAlphaBlendFactor;
232		VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp;
233		colorComponentsAll,		// VkColorComponentFlags	colorWriteMask;
234	};
235
236	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
237	{
238		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
239		DE_NULL,													// const void*									pNext;
240		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
241		VK_FALSE,													// VkBool32										logicOpEnable;
242		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
243		1u,															// deUint32										attachmentCount;
244		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
245		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
246	};
247
248	const VkPipelineShaderStageCreateInfo pShaderStages[] =
249	{
250		{
251			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
252			DE_NULL,												// const void*							pNext;
253			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
254			VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage;
255			vertexModule,											// VkShaderModule						module;
256			"main",													// const char*							pName;
257			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
258		},
259		{
260			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
261			DE_NULL,												// const void*							pNext;
262			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
263			VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits				stage;
264			fragmentModule,											// VkShaderModule						module;
265			"main",													// const char*							pName;
266			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
267		}
268	};
269
270	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
271	{
272		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
273		DE_NULL,											// const void*										pNext;
274		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
275		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
276		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
277		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
278		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
279		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
280		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
281		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
282		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
283		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
284		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
285		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
286		pipelineLayout,										// VkPipelineLayout									layout;
287		renderPass,											// VkRenderPass										renderPass;
288		subpass,											// deUint32											subpass;
289		DE_NULL,											// VkPipeline										basePipelineHandle;
290		0,													// deInt32											basePipelineIndex;
291	};
292
293	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
294}
295
296//! Make a render pass with one subpass per color attachment and one attachment per image layer.
297Move<VkRenderPass> makeRenderPass (const DeviceInterface&		vk,
298								   const VkDevice				device,
299								   const VkFormat				colorFormat,
300								   const deUint32				numLayers)
301{
302	const VkAttachmentDescription colorAttachmentDescription =
303	{
304		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags;
305		colorFormat,								// VkFormat							format;
306		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples;
307		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp;
308		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
309		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
310		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
311		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout;
312		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					finalLayout;
313	};
314	const vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
315
316	// Create a subpass for each attachment (each attachement is a layer of an arrayed image).
317	vector<VkAttachmentReference>	colorAttachmentReferences(numLayers);
318	vector<VkSubpassDescription>	subpasses;
319
320	for (deUint32 i = 0; i < numLayers; ++i)
321	{
322		const VkAttachmentReference attachmentRef =
323		{
324			i,												// deUint32			attachment;
325			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL		// VkImageLayout	layout;
326		};
327		colorAttachmentReferences[i] = attachmentRef;
328
329		const VkSubpassDescription subpassDescription =
330		{
331			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
332			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
333			0u,									// deUint32							inputAttachmentCount;
334			DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
335			1u,									// deUint32							colorAttachmentCount;
336			&colorAttachmentReferences[i],		// const VkAttachmentReference*		pColorAttachments;
337			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
338			DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
339			0u,									// deUint32							preserveAttachmentCount;
340			DE_NULL								// const deUint32*					pPreserveAttachments;
341		};
342		subpasses.push_back(subpassDescription);
343	}
344
345	const VkRenderPassCreateInfo renderPassInfo =
346	{
347		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
348		DE_NULL,												// const void*						pNext;
349		(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
350		static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
351		&attachmentDescriptions[0],								// const VkAttachmentDescription*	pAttachments;
352		static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
353		&subpasses[0],											// const VkSubpassDescription*		pSubpasses;
354		0u,														// deUint32							dependencyCount;
355		DE_NULL													// const VkSubpassDependency*		pDependencies;
356	};
357
358	return createRenderPass(vk, device, &renderPassInfo);
359}
360
361Move<VkImage> makeImage (const DeviceInterface&		vk,
362						 const VkDevice				device,
363						 VkImageCreateFlags			flags,
364						 VkImageType				imageType,
365						 const VkFormat				format,
366						 const IVec3&				size,
367						 const deUint32				numLayers,
368						 const VkImageUsageFlags	usage)
369{
370	const VkImageCreateInfo imageParams =
371	{
372		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
373		DE_NULL,								// const void*				pNext;
374		flags,									// VkImageCreateFlags		flags;
375		imageType,								// VkImageType				imageType;
376		format,									// VkFormat					format;
377		makeExtent3D(size),						// VkExtent3D				extent;
378		1u,										// deUint32					mipLevels;
379		numLayers,								// deUint32					arrayLayers;
380		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
381		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
382		usage,									// VkImageUsageFlags		usage;
383		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
384		0u,										// deUint32					queueFamilyIndexCount;
385		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
386		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
387	};
388	return createImage(vk, device, &imageParams);
389}
390
391inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
392{
393	const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
394	return createBuffer(vk, device, &bufferCreateInfo);
395}
396
397inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
398{
399	return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
400}
401
402//! Get a reference clear value based on color format.
403VkClearValue getClearValue (const VkFormat format)
404{
405	if (isUintFormat(format) || isIntFormat(format))
406		return makeClearValueColorU32(REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE);
407	else
408		return makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
409}
410
411std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
412{
413	std::ostringstream str;
414	if (numComponents == 1)
415		str << (isUint ? "uint" : isSint ? "int" : "float");
416	else
417		str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
418
419	return str.str();
420}
421
422//! A half-viewport quad. Use with TRIANGLE_STRIP topology.
423vector<Vertex4RGBA> genFullQuadVertices (const int subpassCount, const vector<Vec4>& color)
424{
425	vector<Vertex4RGBA>	vectorData;
426	for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
427	{
428		Vertex4RGBA data =
429		{
430			Vec4(0.0f, -1.0f, 0.0f, 1.0f),
431			color[subpassNdx % color.size()],
432		};
433		vectorData.push_back(data);
434		data.position	= Vec4(0.0f,  1.0f, 0.0f, 1.0f);
435		vectorData.push_back(data);
436		data.position	= Vec4(1.0f, -1.0f, 0.0f, 1.0f);
437		vectorData.push_back(data);
438		data.position	= Vec4(1.0f,  1.0f, 0.0f, 1.0f);
439		vectorData.push_back(data);
440	}
441	return vectorData;
442}
443
444VkImageType getImageType (const VkImageViewType viewType)
445{
446	switch (viewType)
447	{
448	case VK_IMAGE_VIEW_TYPE_1D:
449	case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
450		return VK_IMAGE_TYPE_1D;
451
452	case VK_IMAGE_VIEW_TYPE_2D:
453	case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
454	case VK_IMAGE_VIEW_TYPE_CUBE:
455	case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
456		return VK_IMAGE_TYPE_2D;
457
458	case VK_IMAGE_VIEW_TYPE_3D:
459		return VK_IMAGE_TYPE_3D;
460
461	default:
462		DE_ASSERT(0);
463		return VK_IMAGE_TYPE_LAST;
464	}
465}
466
467void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
468{
469	const int	numComponents	= getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
470	const bool	isUint			= isUintFormat(caseDef.colorFormat);
471	const bool	isSint			= isIntFormat(caseDef.colorFormat);
472
473	// Vertex shader
474	{
475		std::ostringstream src;
476		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
477			<< "\n"
478			<< "layout(location = 0) in  vec4 in_position;\n"
479			<< "layout(location = 1) in  vec4 in_color;\n"
480			<< "layout(location = 0) out vec4 out_color;\n"
481			<< "\n"
482			<< "out gl_PerVertex {\n"
483			<< "	vec4 gl_Position;\n"
484			<< "};\n"
485			<< "\n"
486			<< "void main(void)\n"
487			<< "{\n"
488			<< "	gl_Position	= in_position;\n"
489			<< "	out_color	= in_color;\n"
490			<< "}\n";
491
492		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
493	}
494
495	// Fragment shader
496	{
497		std::ostringstream colorValue;
498		colorValue << REFERENCE_COLOR_VALUE;
499		const std::string colorFormat	= getColorFormatStr(numComponents, isUint, isSint);
500		const std::string colorInteger	= (isUint || isSint ? " * "+colorFormat+"("+colorValue.str()+")" :"");
501
502		std::ostringstream src;
503		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
504			<< "\n"
505			<< "layout(location = 0) in  vec4 in_color;\n"
506			<< "layout(location = 0) out " << colorFormat << " o_color;\n"
507			<< "\n"
508			<< "void main(void)\n"
509			<< "{\n"
510			<< "    o_color = " << colorFormat << "("
511			<< (numComponents == 1 ? "in_color.r"   :
512				numComponents == 2 ? "in_color.rg"  :
513				numComponents == 3 ? "in_color.rgb" : "in_color")
514			<< colorInteger
515			<< ");\n"
516			<< "}\n";
517
518		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
519	}
520}
521
522tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef, const Vec4* color, const int sizeColor)
523{
524	const bool						isInt			= isUintFormat(caseDef.colorFormat) || isIntFormat(caseDef.colorFormat);
525	const tcu::PixelBufferAccess	expectedImage	(textureLevel);
526
527	if (isInt)
528		tcu::clear(expectedImage, tcu::IVec4(REFERENCE_COLOR_VALUE));
529	else
530		tcu::clear(expectedImage, tcu::Vec4(1.0));
531
532	for (int z = 0; z < expectedImage.getDepth(); ++z)
533	{
534		const Vec4& setColor	= color[z % sizeColor];
535		const IVec4 setColorInt	= (static_cast<float>(REFERENCE_COLOR_VALUE) * setColor).cast<deInt32>();
536
537		for (int y = 0;							y < caseDef.renderSize.y(); ++y)
538		for (int x = caseDef.renderSize.x()/2;	x < caseDef.renderSize.x(); ++x)
539		{
540			if (isInt)
541				expectedImage.setPixel(setColorInt, x, y, z);
542			else
543				expectedImage.setPixel(setColor, x, y, z);
544		}
545	}
546	return expectedImage;
547}
548
549tcu::TestStatus test (Context& context, const CaseDef caseDef)
550{
551	if (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType &&
552		(!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1")))
553		TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
554
555	const DeviceInterface&			vk					= context.getDeviceInterface();
556	const VkDevice					device				= context.getDevice();
557	const VkQueue					queue				= context.getUniversalQueue();
558	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
559	Allocator&						allocator			= context.getDefaultAllocator();
560	Move<VkImage>					colorImage;
561	MovePtr<Allocation>				colorImageAlloc;
562	const Vec4						color[]				=
563	{
564		Vec4(0.9f, 0.0f, 0.0f, 1.0f),
565		Vec4(0.6f, 1.0f, 0.0f, 1.0f),
566		Vec4(0.3f, 0.0f, 1.0f, 1.0f),
567		Vec4(0.1f, 0.0f, 1.0f, 1.0f)
568	};
569
570	const int						numLayers			= (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? caseDef.renderSize.z() : caseDef.numLayers);
571	const VkDeviceSize				colorBufferSize		= caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.renderSize.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
572	const Unique<VkBuffer>			colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
573	const UniquePtr<Allocation>		colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
574
575	const Unique<VkShaderModule>	vertexModule		(createShaderModule			(vk, device, context.getBinaryCollection().get("vert"), 0u));
576	const Unique<VkShaderModule>	fragmentModule		(createShaderModule			(vk, device, context.getBinaryCollection().get("frag"), 0u));
577	const Unique<VkRenderPass>		renderPass			(makeRenderPass				(vk, device, caseDef.colorFormat, static_cast<deUint32>(numLayers)));
578	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout			(vk, device));
579	vector<SharedPtrVkPipeline>		pipeline;
580	const Unique<VkCommandPool>		cmdPool				(makeCommandPool  (vk, device, queueFamilyIndex));
581	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
582
583	vector<SharedPtrVkImageView>	colorAttachments;
584	vector<VkImageView>				attachmentHandles;
585	Move<VkBuffer>					vertexBuffer;
586	MovePtr<Allocation>				vertexBufferAlloc;
587	Move<VkFramebuffer>				framebuffer;
588
589	//create colorImage
590	{
591		const VkImageViewCreateFlags	flags			= (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? (VkImageViewCreateFlags)VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageViewCreateFlags)0);
592		const VkImageUsageFlags			colorImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
593		colorImage = makeImage(vk, device, flags, getImageType(caseDef.imageType), caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, colorImageUsage);
594		colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
595	}
596
597	//create vertexBuffer
598	{
599		const vector<Vertex4RGBA>	vertices			= genFullQuadVertices(numLayers, vector<Vec4>(color, color + DE_LENGTH_OF_ARRAY(color)));
600		const VkDeviceSize			vertexBufferSize	= sizeInBytes(vertices);
601
602		vertexBuffer		= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
603		vertexBufferAlloc	= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
604		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
605		flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
606	}
607
608	//create attachmentHandles and pipelines
609	for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
610	{
611		const VkImageViewType	imageType = (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY :
612											(VK_IMAGE_VIEW_TYPE_CUBE == caseDef.imageType || VK_IMAGE_VIEW_TYPE_CUBE_ARRAY == caseDef.imageType ? VK_IMAGE_VIEW_TYPE_2D :
613											caseDef.imageType));
614
615		colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, *colorImage, imageType, caseDef.colorFormat, makeColorSubresourceRange(layerNdx, 1))));
616		attachmentHandles.push_back(**colorAttachments.back());
617
618		pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
619															  caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, static_cast<deUint32>(layerNdx))));
620	}
621
622	framebuffer = makeFramebuffer(vk, device, *renderPass, numLayers, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
623
624	beginCommandBuffer(vk, *cmdBuffer);
625	{
626		const vector<VkClearValue>	clearValues			(numLayers, getClearValue(caseDef.colorFormat));
627		const VkRect2D				renderArea			=
628		{
629			makeOffset2D(0, 0),
630			makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
631		};
632		const VkRenderPassBeginInfo	renderPassBeginInfo	=
633		{
634			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType         sType;
635			DE_NULL,									// const void*             pNext;
636			*renderPass,								// VkRenderPass            renderPass;
637			*framebuffer,								// VkFramebuffer           framebuffer;
638			renderArea,									// VkRect2D                renderArea;
639			static_cast<deUint32>(clearValues.size()),	// uint32_t                clearValueCount;
640			&clearValues[0],							// const VkClearValue*     pClearValues;
641		};
642		const VkDeviceSize			vertexBufferOffset	= 0ull;
643
644		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
645		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
646	}
647
648	//cmdDraw
649	for (deUint32 layerNdx = 0; layerNdx < static_cast<deUint32>(numLayers); ++layerNdx)
650	{
651		if (layerNdx != 0)
652			vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
653
654		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
655		vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
656	}
657
658	vk.cmdEndRenderPass(*cmdBuffer);
659
660	// copy colorImage -> host visible colorBuffer
661	{
662		const VkImageMemoryBarrier	imageBarriers[]	=
663		{
664			{
665				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
666				DE_NULL,										// const void*				pNext;
667				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			outputMask;
668				VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags			inputMask;
669				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			oldLayout;
670				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout			newLayout;
671				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
672				VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
673				*colorImage,									// VkImage					image;
674				makeColorSubresourceRange(0, caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
675			}
676		};
677
678		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
679							  0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
680
681		const VkBufferImageCopy		region			=
682		{
683			0ull,																				// VkDeviceSize                bufferOffset;
684			0u,																					// uint32_t                    bufferRowLength;
685			0u,																					// uint32_t                    bufferImageHeight;
686			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers),	// VkImageSubresourceLayers    imageSubresource;
687			makeOffset3D(0, 0, 0),																// VkOffset3D                  imageOffset;
688			makeExtent3D(caseDef.renderSize),													// VkExtent3D                  imageExtent;
689		};
690
691		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
692
693		const VkBufferMemoryBarrier	bufferBarriers[] =
694		{
695			{
696				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
697				DE_NULL,									// const void*        pNext;
698				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
699				VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
700				VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
701				VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
702				*colorBuffer,								// VkBuffer           buffer;
703				0ull,										// VkDeviceSize       offset;
704				VK_WHOLE_SIZE,								// VkDeviceSize       size;
705			},
706		};
707
708		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
709							  0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
710	}
711
712	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
713	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
714
715	// Verify results
716	{
717		invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
718
719		const tcu::TextureFormat			format			= mapVkFormat(caseDef.colorFormat);
720		const int							depth			= deMax32(caseDef.renderSize.z(), caseDef.numLayers);
721		tcu::TextureLevel					textureLevel	(format, caseDef.renderSize.x(), caseDef.renderSize.y(), depth);
722		const tcu::PixelBufferAccess		expectedImage	= getExpectedData (textureLevel, caseDef, color, DE_LENGTH_OF_ARRAY(color));
723		const tcu::ConstPixelBufferAccess	resultImage		(format, caseDef.renderSize.x(), caseDef.renderSize.y(), depth, colorBufferAlloc->getHostPtr());
724
725		if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT))
726			return tcu::TestStatus::fail("Fail");
727	}
728	return tcu::TestStatus::pass("Pass");
729}
730
731std::string getSizeString (const IVec3& size, const int numLayer)
732{
733	std::ostringstream str;
734							str <<		  size.x();
735	if (size.y() > 1)		str << "x" << size.y();
736	if (size.z() > 1)		str << "x" << size.z();
737	if (numLayer > 1)		str << "_" << numLayer;
738
739	return str.str();
740}
741
742std::string getFormatString (const VkFormat format)
743{
744	std::string name(getFormatName(format));
745	return de::toLower(name.substr(10));
746}
747
748std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
749{
750	std::string s(getImageViewTypeName(imageViewType));
751	return de::toLower(s.substr(19));
752}
753
754CaseDef caseDefWithFormat (CaseDef caseDef, const VkFormat format)
755{
756	caseDef.colorFormat = format;
757	return caseDef;
758}
759
760void addTestCasesWithFunctions (tcu::TestCaseGroup* group)
761{
762	const CaseDef caseDef[] =
763	{
764		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(54,  1, 1),	1,		VK_FORMAT_UNDEFINED},
765		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(54,  1, 1),	4,		VK_FORMAT_UNDEFINED},
766		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(22, 64, 1),	1,		VK_FORMAT_UNDEFINED},
767		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(22, 64, 1),	4,		VK_FORMAT_UNDEFINED},
768		{ VK_IMAGE_VIEW_TYPE_3D,			IVec3(22, 64, 7),	1,		VK_FORMAT_UNDEFINED},
769		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(35, 35, 1),	6,		VK_FORMAT_UNDEFINED},
770		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(35, 35, 1),	2*6,	VK_FORMAT_UNDEFINED},
771	};
772
773	const VkFormat format[]	=
774	{
775		VK_FORMAT_R8G8B8A8_UNORM,
776		VK_FORMAT_R32_UINT,
777		VK_FORMAT_R16G16_SINT,
778		VK_FORMAT_R32G32B32A32_SFLOAT,
779	};
780
781	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
782	{
783		MovePtr<tcu::TestCaseGroup>	imageGroup(new tcu::TestCaseGroup(group->getTestContext(), getShortImageViewTypeName(caseDef[sizeNdx].imageType).c_str(), ""));
784		{
785			MovePtr<tcu::TestCaseGroup>	sizeGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeString(caseDef[sizeNdx].renderSize, caseDef[sizeNdx].numLayers).c_str(), ""));
786
787			for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
788				addFunctionCaseWithPrograms(sizeGroup.get(), getFormatString(format[formatNdx]).c_str(), "", initPrograms, test, caseDefWithFormat(caseDef[sizeNdx], format[formatNdx]));
789
790			imageGroup->addChild(sizeGroup.release());
791		}
792		group->addChild(imageGroup.release());
793	}
794}
795
796} // anonymous ns
797
798tcu::TestCaseGroup* createRenderToImageTests (tcu::TestContext& testCtx)
799{
800	return createTestGroup(testCtx, "render_to_image", "Render to image tests", addTestCasesWithFunctions);
801}
802
803} // pipeline
804} // vkt
805