• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Use of gl_Layer in Vertex and Tessellation Shaders
23  *        (part of VK_EXT_ShaderViewportIndexLayer)
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktDrawShaderLayerTests.hpp"
27 
28 #include "vktDrawBaseClass.hpp"
29 #include "vktTestCaseUtil.hpp"
30 
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 
40 #include "tcuTestLog.hpp"
41 #include "tcuVector.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuTextureUtil.hpp"
44 
45 #include "deUniquePtr.hpp"
46 #include "deMath.h"
47 
48 #include <vector>
49 
50 namespace vkt
51 {
52 namespace Draw
53 {
54 using namespace vk;
55 using de::UniquePtr;
56 using de::MovePtr;
57 using de::SharedPtr;
58 using tcu::Vec4;
59 using tcu::Vec2;
60 using tcu::UVec2;
61 using tcu::UVec4;
62 
63 namespace
64 {
65 
66 enum Constants
67 {
68 	MIN_MAX_FRAMEBUFFER_LAYERS = 256,	//!< Minimum number of framebuffer layers.
69 	MIN_MAX_VIEWPORTS = 16,				//!< Minimum number of viewports for an implementation supporting multiViewport.
70 };
71 
72 template<typename T>
sizeInBytes(const std::vector<T> & vec)73 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
74 {
75 	return vec.size() * sizeof(vec[0]);
76 }
77 
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)78 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
79 										 const VkBufferUsageFlags	usage)
80 {
81 	const VkBufferCreateInfo bufferCreateInfo =
82 	{
83 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
84 		DE_NULL,								// const void*			pNext;
85 		(VkBufferCreateFlags)0,					// VkBufferCreateFlags	flags;
86 		bufferSize,								// VkDeviceSize			size;
87 		usage,									// VkBufferUsageFlags	usage;
88 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
89 		0u,										// deUint32				queueFamilyIndexCount;
90 		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
91 	};
92 	return bufferCreateInfo;
93 }
94 
makePipelineLayout(const DeviceInterface & vk,const VkDevice device)95 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
96 										   const VkDevice				device)
97 {
98 	const VkPipelineLayoutCreateInfo info =
99 	{
100 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
101 		DE_NULL,											// const void*					pNext;
102 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
103 		0u,													// deUint32						setLayoutCount;
104 		DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
105 		0u,													// deUint32						pushConstantRangeCount;
106 		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
107 	};
108 	return createPipelineLayout(vk, device, &info);
109 }
110 
makeImageView(const DeviceInterface & vk,const VkDevice vkDevice,const VkImage image,const VkImageViewType viewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)111 Move<VkImageView> makeImageView (const DeviceInterface&			vk,
112 								 const VkDevice					vkDevice,
113 								 const VkImage					image,
114 								 const VkImageViewType			viewType,
115 								 const VkFormat					format,
116 								 const VkImageSubresourceRange	subresourceRange)
117 {
118 	const VkImageViewCreateInfo imageViewParams =
119 	{
120 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
121 		DE_NULL,										// const void*				pNext;
122 		(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
123 		image,											// VkImage					image;
124 		viewType,										// VkImageViewType			viewType;
125 		format,											// VkFormat					format;
126 		makeComponentMappingRGBA(),						// VkComponentMapping		components;
127 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
128 	};
129 	return createImageView(vk, vkDevice, &imageViewParams);
130 }
131 
beginCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)132 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
133 {
134 	const VkCommandBufferBeginInfo info =
135 	{
136 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
137 		DE_NULL,										// const void*                              pNext;
138 		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags                flags;
139 		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
140 	};
141 	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
142 }
143 
submitCommandsAndWait(const DeviceInterface & vk,const VkDevice device,const VkQueue queue,const VkCommandBuffer commandBuffer)144 void submitCommandsAndWait (const DeviceInterface&	vk,
145 							const VkDevice			device,
146 							const VkQueue			queue,
147 							const VkCommandBuffer	commandBuffer)
148 {
149 	const Unique<VkFence> fence(createFence(vk, device));
150 
151 	const VkSubmitInfo submitInfo =
152 	{
153 		VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType                sType;
154 		DE_NULL,							// const void*                    pNext;
155 		0u,									// uint32_t                       waitSemaphoreCount;
156 		DE_NULL,							// const VkSemaphore*             pWaitSemaphores;
157 		DE_NULL,							// const VkPipelineStageFlags*    pWaitDstStageMask;
158 		1u,									// uint32_t                       commandBufferCount;
159 		&commandBuffer,						// const VkCommandBuffer*         pCommandBuffers;
160 		0u,									// uint32_t                       signalSemaphoreCount;
161 		DE_NULL,							// const VkSemaphore*             pSignalSemaphores;
162 	};
163 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
164 	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
165 }
166 
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const deUint32 width,const deUint32 height,const deUint32 layers=1u)167 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
168 									 const VkDevice				device,
169 									 const VkRenderPass			renderPass,
170 									 const deUint32				attachmentCount,
171 									 const VkImageView*			pAttachments,
172 									 const deUint32				width,
173 									 const deUint32				height,
174 									 const deUint32				layers = 1u)
175 {
176 	const VkFramebufferCreateInfo framebufferInfo = {
177 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
178 		DE_NULL,										// const void*                                 pNext;
179 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
180 		renderPass,										// VkRenderPass                                renderPass;
181 		attachmentCount,								// uint32_t                                    attachmentCount;
182 		pAttachments,									// const VkImageView*                          pAttachments;
183 		width,											// uint32_t                                    width;
184 		height,											// uint32_t                                    height;
185 		layers,											// uint32_t                                    layers;
186 	};
187 
188 	return createFramebuffer(vk, device, &framebufferInfo);
189 }
190 
bindImage(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkImage image,const MemoryRequirement requirement)191 MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
192 {
193 	MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
194 	VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
195 	return alloc;
196 }
197 
makeImage(const vk::DeviceInterface & vk,const vk::VkDevice device,const vk::VkImageCreateInfo & createInfo)198 inline vk::Move<vk::VkImage> makeImage (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkImageCreateInfo& createInfo)
199 {
200 	return createImage(vk, device, &createInfo);
201 }
202 
makeImageCreateInfo(const VkFormat format,const UVec2 & size,const deUint32 numLayers,VkImageUsageFlags usage)203 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, const deUint32 numLayers, VkImageUsageFlags usage)
204 {
205 	const VkImageCreateInfo imageParams =
206 	{
207 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
208 		DE_NULL,										// const void*				pNext;
209 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
210 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
211 		format,											// VkFormat					format;
212 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
213 		1u,												// deUint32					mipLevels;
214 		numLayers,										// deUint32					arrayLayers;
215 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
216 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
217 		usage,											// VkImageUsageFlags		usage;
218 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
219 		0u,												// deUint32					queueFamilyIndexCount;
220 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
221 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
222 	};
223 	return imageParams;
224 }
225 
226 //! A single-attachment, single-subpass render pass.
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)227 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
228 								   const VkDevice			device,
229 								   const VkFormat			colorFormat)
230 {
231 	const VkAttachmentDescription colorAttachmentDescription =
232 	{
233 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
234 		colorFormat,										// VkFormat							format;
235 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
236 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
237 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
238 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
239 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
240 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
241 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
242 	};
243 
244 	const VkAttachmentReference colorAttachmentRef =
245 	{
246 		0u,													// deUint32			attachment;
247 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
248 	};
249 
250 	const VkSubpassDescription subpassDescription =
251 	{
252 		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
253 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
254 		0u,													// deUint32							inputAttachmentCount;
255 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
256 		1u,													// deUint32							colorAttachmentCount;
257 		&colorAttachmentRef,								// const VkAttachmentReference*		pColorAttachments;
258 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
259 		DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
260 		0u,													// deUint32							preserveAttachmentCount;
261 		DE_NULL												// const deUint32*					pPreserveAttachments;
262 	};
263 
264 	const VkRenderPassCreateInfo renderPassInfo =
265 	{
266 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
267 		DE_NULL,											// const void*						pNext;
268 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
269 		1u,													// deUint32							attachmentCount;
270 		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
271 		1u,													// deUint32							subpassCount;
272 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
273 		0u,													// deUint32							dependencyCount;
274 		DE_NULL												// const VkSubpassDependency*		pDependencies;
275 	};
276 
277 	return createRenderPass(vk, device, &renderPassInfo);
278 }
279 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule tessellationControlModule,const VkShaderModule tessellationEvaluationModule,const VkShaderModule fragmentModule,const UVec2 renderSize)280 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
281 									   const VkDevice				device,
282 									   const VkPipelineLayout		pipelineLayout,
283 									   const VkRenderPass			renderPass,
284 									   const VkShaderModule			vertexModule,
285 									   const VkShaderModule			tessellationControlModule,
286 									   const VkShaderModule			tessellationEvaluationModule,
287 									   const VkShaderModule			fragmentModule,
288 									   const UVec2					renderSize)
289 {
290 	const VkVertexInputBindingDescription vertexInputBindingDescription =
291 	{
292 		0u,								// uint32_t				binding;
293 		sizeof(PositionColorVertex),	// uint32_t				stride;
294 		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
295 	};
296 
297 	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
298 	{
299 		{
300 			0u,									// uint32_t			location;
301 			0u,									// uint32_t			binding;
302 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
303 			0u,									// uint32_t			offset;
304 		},
305 		{
306 			1u,									// uint32_t			location;
307 			0u,									// uint32_t			binding;
308 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
309 			sizeof(Vec4),						// uint32_t			offset;
310 		},
311 	};
312 
313 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
314 	{
315 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
316 		DE_NULL,														// const void*                                 pNext;
317 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
318 		1u,																// uint32_t                                    vertexBindingDescriptionCount;
319 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
320 		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),			// uint32_t                                    vertexAttributeDescriptionCount;
321 		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
322 	};
323 
324 	const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
325 
326 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
327 	{
328 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,										// VkStructureType                             sType;
329 		DE_NULL,																							// const void*                                 pNext;
330 		(VkPipelineInputAssemblyStateCreateFlags)0,															// VkPipelineInputAssemblyStateCreateFlags     flags;
331 		useTessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// VkPrimitiveTopology                         topology;
332 		VK_FALSE,																							// VkBool32                                    primitiveRestartEnable;
333 	};
334 
335 
336 	VkViewport viewport = makeViewport(0.0f, 0.0f, static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 0.0f, 1.0f);
337 	VkRect2D rectScissor = { { 0, 0 }, { renderSize.x(), renderSize.y() } };
338 
339 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
340 	{
341 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType                             sType;
342 		DE_NULL,														// const void*                                 pNext;
343 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags          flags;
344 		1u,																// uint32_t                                    viewportCount;
345 		&viewport,														// const VkViewport*                           pViewports;
346 		1u,																// uint32_t                                    scissorCount;
347 		&rectScissor,													// const VkRect2D*                             pScissors;
348 	};
349 
350 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
351 	{
352 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
353 		DE_NULL,														// const void*                              pNext;
354 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
355 		VK_FALSE,														// VkBool32                                 depthClampEnable;
356 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
357 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
358 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
359 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
360 		VK_FALSE,														// VkBool32									depthBiasEnable;
361 		0.0f,															// float									depthBiasConstantFactor;
362 		0.0f,															// float									depthBiasClamp;
363 		0.0f,															// float									depthBiasSlopeFactor;
364 		1.0f,															// float									lineWidth;
365 	};
366 
367 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
368 	{
369 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
370 		DE_NULL,														// const void*								pNext;
371 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags	flags;
372 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
373 		VK_FALSE,														// VkBool32									sampleShadingEnable;
374 		0.0f,															// float									minSampleShading;
375 		DE_NULL,														// const VkSampleMask*						pSampleMask;
376 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
377 		VK_FALSE														// VkBool32									alphaToOneEnable;
378 	};
379 
380 	const VkStencilOpState stencilOpState = makeStencilOpState(
381 		VK_STENCIL_OP_KEEP,				// stencil fail
382 		VK_STENCIL_OP_KEEP,				// depth & stencil pass
383 		VK_STENCIL_OP_KEEP,				// depth only fail
384 		VK_COMPARE_OP_ALWAYS,			// compare op
385 		0u,								// compare mask
386 		0u,								// write mask
387 		0u);							// reference
388 
389 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
390 	{
391 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType							sType;
392 		DE_NULL,														// const void*								pNext;
393 		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags	flags;
394 		VK_FALSE,														// VkBool32									depthTestEnable;
395 		VK_FALSE,														// VkBool32									depthWriteEnable;
396 		VK_COMPARE_OP_LESS,												// VkCompareOp								depthCompareOp;
397 		VK_FALSE,														// VkBool32									depthBoundsTestEnable;
398 		VK_FALSE,														// VkBool32									stencilTestEnable;
399 		stencilOpState,													// VkStencilOpState							front;
400 		stencilOpState,													// VkStencilOpState							back;
401 		0.0f,															// float									minDepthBounds;
402 		1.0f,															// float									maxDepthBounds;
403 	};
404 
405 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
406 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState	=
407 	{
408 		VK_FALSE,						// VkBool32					blendEnable;
409 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
410 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
411 		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
412 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
413 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
414 		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
415 		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
416 	};
417 
418 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
419 	{
420 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
421 		DE_NULL,														// const void*									pNext;
422 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
423 		VK_FALSE,														// VkBool32										logicOpEnable;
424 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
425 		1u,																// deUint32										attachmentCount;
426 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
427 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
428 	};
429 
430 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
431 	{
432 		{
433 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
434 			DE_NULL,													// const void*							pNext;
435 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
436 			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
437 			vertexModule,												// VkShaderModule						module;
438 			"main",														// const char*							pName;
439 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
440 		},
441 		{
442 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
443 			DE_NULL,													// const void*							pNext;
444 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
445 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
446 			fragmentModule,												// VkShaderModule						module;
447 			"main",														// const char*							pName;
448 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
449 		},
450 		{
451 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
452 			DE_NULL,													// const void*							pNext;
453 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
454 			VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,					// VkShaderStageFlagBits				stage;
455 			tessellationControlModule,									// VkShaderModule						module;
456 			"main",														// const char*							pName;
457 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
458 		},
459 		{
460 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
461 			DE_NULL,													// const void*							pNext;
462 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
463 			VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,				// VkShaderStageFlagBits				stage;
464 			tessellationEvaluationModule,								// VkShaderModule						module;
465 			"main",														// const char*							pName;
466 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
467 		},
468 	};
469 
470 	const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
471 	{
472 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType							sType;
473 		DE_NULL,														// const void*								pNext;
474 		(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags	flags;
475 		3,																// uint32_t									patchControlPoints;
476 	};
477 
478 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
479 	{
480 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,					// VkStructureType									sType;
481 		DE_NULL,															// const void*										pNext;
482 		(VkPipelineCreateFlags)0,											// VkPipelineCreateFlags							flags;
483 		useTessellationShaders ? deUint32(4) : deUint32(2),					// deUint32											stageCount;
484 		pShaderStages,														// const VkPipelineShaderStageCreateInfo*			pStages;
485 		&vertexInputStateInfo,												// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
486 		&pipelineInputAssemblyStateInfo,									// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
487 		useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL,	// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
488 		&pipelineViewportStateInfo,											// const VkPipelineViewportStateCreateInfo*			pViewportState;
489 		&pipelineRasterizationStateInfo,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
490 		&pipelineMultisampleStateInfo,										// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
491 		&pipelineDepthStencilStateInfo,										// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
492 		&pipelineColorBlendStateInfo,										// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
493 		DE_NULL,															// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
494 		pipelineLayout,														// VkPipelineLayout									layout;
495 		renderPass,															// VkRenderPass										renderPass;
496 		0u,																	// deUint32											subpass;
497 		DE_NULL,															// VkPipeline										basePipelineHandle;
498 		0,																	// deInt32											basePipelineIndex;
499 	};
500 
501 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
502 }
503 
504 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const Vec4 & clearColor,const UVec4 & cell,const Vec4 & cellColor)505 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat	format,
506 										  const UVec2&				renderSize,
507 										  const Vec4&				clearColor,
508 										  const UVec4&				cell,
509 										  const Vec4&				cellColor)
510 {
511 	tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
512 	tcu::clear(image.getAccess(), clearColor);
513 
514 	tcu::clear(tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
515 			   cellColor);
516 
517 	return image;
518 }
519 
initVertexTestPrograms(SourceCollections & programCollection,const int numViewports)520 void initVertexTestPrograms (SourceCollections& programCollection, const int numViewports)
521 {
522 	DE_UNREF(numViewports);
523 
524 	// Vertex shader
525 	{
526 		std::ostringstream src;
527 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
528 			<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
529 			<< "\n"
530 			<< "layout(location = 0) in  vec4 in_position;\n"
531 			<< "layout(location = 1) in  vec4 in_color;\n"
532 			<< "layout(location = 0) out vec4 out_color;\n"
533 			<< "\n"
534 			<< "void main(void)\n"
535 			<< "{\n"
536 			<< "    gl_Layer = gl_VertexIndex / 6;\n"
537 			<< "    gl_Position = in_position;\n"
538 			<< "    out_color = in_color;\n"
539 			<< "}\n";
540 
541 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
542 	}
543 
544 	// Fragment shader
545 	{
546 		std::ostringstream src;
547 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
548 			<< "\n"
549 			<< "layout(location = 0) in  vec4 in_color;\n"
550 			<< "layout(location = 0) out vec4 out_color;\n"
551 			<< "\n"
552 			<< "void main(void)\n"
553 			<< "{\n"
554 			<< "    out_color = in_color;\n"
555 			<< "}\n";
556 
557 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
558 	}
559 }
560 
initTessellationTestPrograms(SourceCollections & programCollection,const int numViewports)561 void initTessellationTestPrograms (SourceCollections& programCollection, const int numViewports)
562 {
563 	DE_UNREF(numViewports);
564 
565 	// Vertex shader
566 	{
567 		std::ostringstream src;
568 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
569 			<< "\n"
570 			<< "layout(location = 0) in  vec4 in_position;\n"
571 			<< "layout(location = 1) in  vec4 in_color;\n"
572 			<< "layout(location = 0) out vec4 out_color;\n"
573 			<< "\n"
574 			<< "void main(void)\n"
575 			<< "{\n"
576 			<< "    gl_Position = in_position;\n"
577 			<< "    out_color = in_color;\n"
578 			<< "}\n";
579 
580 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
581 	}
582 
583 	// Tessellation control shader
584 	{
585 		std::ostringstream src;
586 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
587 			<< "\n"
588 			<< "layout(vertices = 3) out;\n"
589 			<< "\n"
590 			<< "layout(location = 0) in  vec4 in_color[];\n"
591 			<< "layout(location = 0) out vec4 out_color[];\n"
592 			<< "\n"
593 			<< "void main(void)\n"
594 			<< "{\n"
595 			<< "    if (gl_InvocationID == 0) {\n"
596 			<< "        gl_TessLevelInner[0] = 1.0;\n"
597 			<< "        gl_TessLevelInner[1] = 1.0;\n"
598 			<< "        gl_TessLevelOuter[0] = 1.0;\n"
599 			<< "        gl_TessLevelOuter[1] = 1.0;\n"
600 			<< "        gl_TessLevelOuter[2] = 1.0;\n"
601 			<< "        gl_TessLevelOuter[3] = 1.0;\n"
602 			<< "    }\n"
603 			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
604 			<< "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
605 			<< "}\n";
606 
607 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
608 	}
609 
610 	// Tessellation evaluation shader
611 	{
612 		std::ostringstream src;
613 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
614 			<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
615 			<< "\n"
616 			<< "layout(triangles, equal_spacing, cw) in;\n"
617 			<< "\n"
618 			<< "layout(location = 0) in  vec4 in_color[];\n"
619 			<< "layout(location = 0) out vec4 out_color;\n"
620 			<< "\n"
621 			<< "void main(void)\n"
622 			<< "{\n"
623 			<< "    gl_Layer = gl_PrimitiveID / 2;\n"
624 			<< "    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
625 			<< "                  gl_in[1].gl_Position * gl_TessCoord.y +\n"
626 			<< "                  gl_in[2].gl_Position * gl_TessCoord.z;\n"
627 			<< "\n"
628 			<< "    out_color = in_color[0] * gl_TessCoord.x +\n"
629 			<< "                in_color[1] * gl_TessCoord.y +\n"
630 			<< "                in_color[2] * gl_TessCoord.z;\n"
631 			<< "}\n";
632 
633 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
634 	}
635 
636 	// Fragment shader
637 	{
638 		std::ostringstream src;
639 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
640 			<< "\n"
641 			<< "layout(location = 0) in  vec4 in_color;\n"
642 			<< "layout(location = 0) out vec4 out_color;\n"
643 			<< "\n"
644 			<< "void main(void)\n"
645 			<< "{\n"
646 			<< "    out_color = in_color;\n"
647 			<< "}\n";
648 
649 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
650 	}
651 }
652 
generateGrid(const int numCells,const UVec2 & renderSize)653 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
654 {
655 	const int numCols		= deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
656 	const int numRows		= deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
657 	const int rectWidth		= renderSize.x() / numCols;
658 	const int rectHeight	= renderSize.y() / numRows;
659 
660 	std::vector<UVec4> cells;
661 	cells.reserve(numCells);
662 
663 	int x = 0;
664 	int y = 0;
665 
666 	for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
667 	{
668 		const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
669 		if (nextRow)
670 		{
671 			x  = 0;
672 			y += rectHeight;
673 		}
674 
675 		cells.push_back(UVec4(x, y, rectWidth, rectHeight));
676 
677 		x += rectWidth;
678 	}
679 
680 	return cells;
681 }
682 
generateColors(int numColors)683 std::vector<Vec4> generateColors (int numColors)
684 {
685 	const Vec4 colors[] =
686 	{
687 		Vec4(0.18f, 0.42f, 0.17f, 1.0f),
688 		Vec4(0.29f, 0.62f, 0.28f, 1.0f),
689 		Vec4(0.59f, 0.84f, 0.44f, 1.0f),
690 		Vec4(0.96f, 0.95f, 0.72f, 1.0f),
691 		Vec4(0.94f, 0.55f, 0.39f, 1.0f),
692 		Vec4(0.82f, 0.19f, 0.12f, 1.0f),
693 		Vec4(0.46f, 0.15f, 0.26f, 1.0f),
694 		Vec4(0.24f, 0.14f, 0.24f, 1.0f),
695 		Vec4(0.49f, 0.31f, 0.26f, 1.0f),
696 		Vec4(0.78f, 0.52f, 0.33f, 1.0f),
697 		Vec4(0.94f, 0.82f, 0.31f, 1.0f),
698 		Vec4(0.98f, 0.65f, 0.30f, 1.0f),
699 		Vec4(0.22f, 0.65f, 0.53f, 1.0f),
700 		Vec4(0.67f, 0.81f, 0.91f, 1.0f),
701 		Vec4(0.43f, 0.44f, 0.75f, 1.0f),
702 		Vec4(0.26f, 0.24f, 0.48f, 1.0f),
703 	};
704 
705 	std::vector<Vec4> result;
706 	result.reserve(numColors);
707 
708 	for (int i = 0; i < numColors; ++i)
709 	{
710 		result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
711 	}
712 
713 	return result;
714 }
715 
generateVertices(const std::vector<UVec4> & grid,const std::vector<Vec4> & colors,const UVec2 & renderSize)716 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
717 {
718 	DE_ASSERT(colors.size() == grid.size());
719 
720 	// Two triangles for each cell. Each cell correspond to a layer.
721 	std::size_t total = grid.size() * 6;
722 
723 	std::vector<PositionColorVertex> result;
724 	result.reserve(total);
725 
726 	for (std::size_t i = 0; i < total; ++i)
727 	{
728 		Vec4 pos;
729 		pos.z() = 0.0;
730 		pos.w() = 1.0;
731 
732 		Vec4 cell = grid[i/6].asFloat() * 2.0f;
733 		float x			= cell.x() / float(renderSize.x()) - 1.0f;
734 		float y			= cell.y() / float(renderSize.y()) - 1.0f;
735 		float width		= cell.z() / float(renderSize.x());
736 		float height	= cell.w() / float(renderSize.y());
737 
738 		switch (i % 6)
739 		{
740 		case 0: pos.xy() = Vec2(x,			y + height);	break;
741 		case 1: pos.xy() = Vec2(x + width,	y + height);	break;
742 		case 2: pos.xy() = Vec2(x,			y);				break;
743 		case 3: pos.xy() = Vec2(x + width,	y);				break;
744 		case 4: pos.xy() = Vec2(x + width,	y + height);	break;
745 		case 5: pos.xy() = Vec2(x,			y);				break;
746 		}
747 
748 		result.push_back(PositionColorVertex(pos, colors[i/6]));
749 	}
750 
751 	return result;
752 }
753 
754 // Renderer generates two triangles per layer, each pair using a different
755 // color and a different position.
756 class Renderer
757 {
758 public:
759 	enum Shader
760 	{
761 		VERTEX,
762 		TESSELLATION,
763 	};
764 
Renderer(Context & context,const UVec2 & renderSize,const int numLayers,const VkFormat colorFormat,const Vec4 & clearColor,const std::vector<PositionColorVertex> & vertices,const Shader shader)765 	Renderer (Context&									context,
766 			  const UVec2&								renderSize,
767 			  const int									numLayers,
768 			  const VkFormat							colorFormat,
769 			  const Vec4&								clearColor,
770 			  const std::vector<PositionColorVertex>&	vertices,
771 			  const Shader								shader)
772 		: m_renderSize				(renderSize)
773 		, m_colorFormat				(colorFormat)
774 		, m_colorSubresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
775 		, m_clearColor				(clearColor)
776 		, m_numLayers				(numLayers)
777 		, m_vertices				(vertices)
778 	{
779 		const DeviceInterface&		vk					= context.getDeviceInterface();
780 		const VkDevice				device				= context.getDevice();
781 		const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
782 		Allocator&					allocator			= context.getDefaultAllocator();
783 		const VkDeviceSize			vertexBufferSize    = sizeInBytes(m_vertices);
784 
785 		m_colorImage		= makeImage					(vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
786 		m_colorImageAlloc	= bindImage					(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
787 		m_colorAttachment	= makeImageView				(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat, m_colorSubresourceRange);
788 
789 		m_vertexBuffer		= Buffer::createAndAlloc	(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
790 
791 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
792 		flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
793 
794 		if (shader == TESSELLATION)
795 		{
796 			m_tessellationControlModule		= createShaderModule	(vk, device, context.getBinaryCollection().get("tesc"), 0u);
797 			m_tessellationEvaluationModule	= createShaderModule	(vk, device, context.getBinaryCollection().get("tese"), 0u);
798 		}
799 
800 		m_vertexModule		= createShaderModule	(vk, device, context.getBinaryCollection().get("vert"), 0u);
801 		m_fragmentModule	= createShaderModule	(vk, device, context.getBinaryCollection().get("frag"), 0u);
802 		m_renderPass		= makeRenderPass		(vk, device, m_colorFormat);
803 		m_framebuffer		= makeFramebuffer		(vk, device, *m_renderPass, 1u, &m_colorAttachment.get(),
804 													 static_cast<deUint32>(m_renderSize.x()),
805 													 static_cast<deUint32>(m_renderSize.y()),
806 													 numLayers);
807 		m_pipelineLayout	= makePipelineLayout	(vk, device);
808 		m_pipeline			= makeGraphicsPipeline	(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
809 													 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize);
810 		m_cmdPool			= createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
811 		m_cmdBuffer			= allocateCommandBuffer	(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
812 	}
813 
draw(Context & context,const VkBuffer colorBuffer) const814 	void draw (Context& context, const VkBuffer colorBuffer) const
815 	{
816 		const DeviceInterface&		vk			= context.getDeviceInterface();
817 		const VkDevice				device		= context.getDevice();
818 		const VkQueue				queue		= context.getUniversalQueue();
819 
820 		beginCommandBuffer(vk, *m_cmdBuffer);
821 
822 		const VkClearValue			clearValue	= makeClearValueColor(m_clearColor);
823 		const VkRect2D				renderArea	=
824 		{
825 			makeOffset2D(0, 0),
826 			makeExtent2D(m_renderSize.x(), m_renderSize.y()),
827 		};
828 		const VkRenderPassBeginInfo renderPassBeginInfo =
829 		{
830 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
831 			DE_NULL,										// const void*             pNext;
832 			*m_renderPass,									// VkRenderPass            renderPass;
833 			*m_framebuffer,									// VkFramebuffer           framebuffer;
834 			renderArea,										// VkRect2D                renderArea;
835 			1u,												// uint32_t                clearValueCount;
836 			&clearValue,									// const VkClearValue*     pClearValues;
837 		};
838 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
839 
840 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
841 		{
842 			const VkBuffer vertexBuffer = m_vertexBuffer->object();
843 			const VkDeviceSize vertexBufferOffset = 0ull;
844 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
845 		}
846 		vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_numLayers * 6), 1u, 0u, 0u);	// two triangles per layer
847 		vk.cmdEndRenderPass(*m_cmdBuffer);
848 
849 		copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, m_colorSubresourceRange.layerCount);
850 
851 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
852 		submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
853 	}
854 
855 private:
856 	const UVec2								m_renderSize;
857 	const VkFormat							m_colorFormat;
858 	const VkImageSubresourceRange			m_colorSubresourceRange;
859 	const Vec4								m_clearColor;
860 	const int								m_numLayers;
861 	const std::vector<PositionColorVertex>	m_vertices;
862 
863 	Move<VkImage>							m_colorImage;
864 	MovePtr<Allocation>						m_colorImageAlloc;
865 	Move<VkImageView>						m_colorAttachment;
866 	SharedPtr<Buffer>						m_vertexBuffer;
867 	Move<VkShaderModule>					m_vertexModule;
868 	Move<VkShaderModule>					m_tessellationControlModule;
869 	Move<VkShaderModule>					m_tessellationEvaluationModule;
870 	Move<VkShaderModule>					m_fragmentModule;
871 	Move<VkRenderPass>						m_renderPass;
872 	Move<VkFramebuffer>						m_framebuffer;
873 	Move<VkPipelineLayout>					m_pipelineLayout;
874 	Move<VkPipeline>						m_pipeline;
875 	Move<VkCommandPool>						m_cmdPool;
876 	Move<VkCommandBuffer>					m_cmdBuffer;
877 
878 	// "deleted"
879 				Renderer	(const Renderer&);
880 	Renderer&	operator=	(const Renderer&);
881 };
882 
checkRequirements(const Context & context)883 void checkRequirements (const Context& context)
884 {
885 	const VkPhysicalDeviceFeatures	features		= getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice());
886 	const VkPhysicalDeviceLimits	limits			= getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
887 
888 	if (!features.multiViewport)
889 		TCU_THROW(NotSupportedError, "Required feature is not supported: multiViewport");
890 
891 	if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
892 		TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
893 
894 	if (limits.maxViewports < MIN_MAX_VIEWPORTS)
895 		TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
896 
897 	const std::vector<std::string>&	extensions		= context.getDeviceExtensions();
898 	if (!isDeviceExtensionSupported(context.getUsedApiVersion(), extensions, "VK_EXT_shader_viewport_index_layer"))
899 		TCU_THROW(NotSupportedError, "Extension VK_EXT_shader_viewport_index_layer not supported");
900 }
901 
testVertexShader(Context & context,const int numLayers)902 tcu::TestStatus testVertexShader (Context& context, const int numLayers)
903 {
904 	checkRequirements(context);
905 
906 	const DeviceInterface&					vk					= context.getDeviceInterface();
907 	const VkDevice							device				= context.getDevice();
908 	Allocator&								allocator			= context.getDefaultAllocator();
909 
910 	const UVec2								renderSize			(256, 256);
911 	const VkFormat							colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
912 	const Vec4								clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
913 	const std::vector<UVec4>				grid				= generateGrid(numLayers, renderSize);
914 	const std::vector<Vec4>					colors				= generateColors(numLayers);
915 	const std::vector<PositionColorVertex>	vertices			= generateVertices(grid, colors, renderSize);
916 
917 	const VkDeviceSize						colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * numLayers;
918 
919 	const SharedPtr<Buffer>					colorBuffer			= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
920 
921 	// Zero buffer.
922 	{
923 		const Allocation alloc = colorBuffer->getBoundMemory();
924 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
925 		flushAlloc(vk, device, alloc);
926 	}
927 
928 	{
929 		context.getTestContext().getLog()
930 			<< tcu::TestLog::Message << "Rendering a rectangle in each of the " << numLayers << " layer(s)." << tcu::TestLog::EndMessage
931 			<< tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
932 	}
933 
934 	// Draw.
935 	{
936 		const Renderer renderer (context, renderSize, numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
937 		renderer.draw(context, colorBuffer->object());
938 	}
939 
940 	// Verify layers.
941 	{
942 		const Allocation alloc = colorBuffer->getBoundMemory();
943 		invalidateMappedMemoryRange(vk, device, alloc.getMemory(), 0ull, colorBufferSize);
944 
945 		deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
946 		for (int i = 0; i < numLayers; i++)
947 		{
948 			const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / numLayers) * i));
949 			const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
950 			std::string imageSetName = "layer_" + de::toString(i);
951 			std::string imageSetDesc = "Image compare for layer " + de::toString(i);
952 			if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
953 				TCU_FAIL("Rendered image is not correct");
954 		}
955 	}
956 
957 	return tcu::TestStatus::pass("OK");
958 }
959 
testTessellationShader(Context & context,const int numLayers)960 tcu::TestStatus testTessellationShader (Context& context, const int numLayers)
961 {
962 	checkRequirements(context);
963 
964 	const VkPhysicalDeviceFeatures&			features			= context.getDeviceFeatures();
965 	if (!features.tessellationShader)
966 		TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
967 
968 	const DeviceInterface&					vk					= context.getDeviceInterface();
969 	const VkDevice							device				= context.getDevice();
970 	Allocator&								allocator			= context.getDefaultAllocator();
971 
972 	const UVec2								renderSize			(256, 256);
973 	const VkFormat							colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
974 	const Vec4								clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
975 	const std::vector<UVec4>				grid				= generateGrid(numLayers, renderSize);
976 	const std::vector<Vec4>					colors				= generateColors(numLayers);
977 	const std::vector<PositionColorVertex>	vertices			= generateVertices(grid, colors, renderSize);
978 
979 	const VkDeviceSize						colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * numLayers;
980 
981 	const SharedPtr<Buffer>					colorBuffer			= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
982 
983 	// Zero buffer.
984 	{
985 		const Allocation alloc = colorBuffer->getBoundMemory();
986 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
987 		flushAlloc(vk, device, alloc);
988 	}
989 
990 	{
991 		context.getTestContext().getLog()
992 			<< tcu::TestLog::Message << "Rendering a rectangle in each of the " << numLayers << " layer(s)." << tcu::TestLog::EndMessage
993 			<< tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
994 	}
995 
996 	// Draw.
997 	{
998 		const Renderer renderer (context, renderSize, numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
999 		renderer.draw(context, colorBuffer->object());
1000 	}
1001 
1002 	// Verify layers.
1003 	{
1004 		const Allocation alloc = colorBuffer->getBoundMemory();
1005 		invalidateMappedMemoryRange(vk, device, alloc.getMemory(), 0ull, colorBufferSize);
1006 
1007 		deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
1008 		for (int i = 0; i < numLayers; i++) {
1009 			const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / numLayers) * i));
1010 			const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
1011 			std::string imageSetName = "layer_" + de::toString(i);
1012 			std::string imageSetDesc = "Image compare for layer " + de::toString(i);
1013 			if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1014 				TCU_FAIL("Rendered image is not correct");
1015 		}
1016 	}
1017 
1018 	return tcu::TestStatus::pass("OK");
1019 }
1020 
1021 } // anonymous
1022 
createShaderLayerTests(tcu::TestContext & testCtx)1023 tcu::TestCaseGroup* createShaderLayerTests	(tcu::TestContext& testCtx)
1024 {
1025 	MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
1026 
1027 	int numLayersToTest[] =
1028 	{
1029 		1,
1030 		2,
1031 		3,
1032 		4,
1033 		5,
1034 		6,
1035 		7,
1036 		8,
1037 		MIN_MAX_FRAMEBUFFER_LAYERS,
1038 	};
1039 
1040 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1041 	{
1042 		int numLayers = numLayersToTest[i];
1043 		addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(numLayers), "", initVertexTestPrograms, testVertexShader, numLayers);
1044 	}
1045 
1046 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1047 	{
1048 		int numLayers = numLayersToTest[i];
1049 		addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(numLayers), "", initTessellationTestPrograms, testTessellationShader, numLayers);
1050 	}
1051 
1052 	return group.release();
1053 }
1054 
1055 } // Draw
1056 } // vkt
1057