1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 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
21  * \brief Tests fragment density map extension ( VK_EXT_fragment_density_map )
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRenderPassFragmentDensityMapTests.hpp"
25 #include "pipeline/vktPipelineImageUtil.hpp"
26 #include "deMath.h"
27 #include "vktTestCase.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vktCustomInstancesDevices.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "tcuCommandLine.hpp"
38 #include "tcuStringTemplate.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuTestLog.hpp"
41 #include <sstream>
42 #include <vector>
43 #include <set>
44 
45 // Each test generates an image with a color gradient where all colors should be unique when rendered without density map
46 // ( and for multi_view tests - the quantity of each color in a histogram should be 2 instead of 1 ).
47 // The whole density map has the same values defined by input fragment area ( one of the test input parameters ).
48 // With density map enabled - the number of each color in a histogram should be [ fragmentArea.x * fragmentArea.y ]
49 // ( that value will be doubled for multi_view case ).
50 //
51 // Additionally test checks if gl_FragSizeEXT shader variable has proper value ( as defined by fragmentArea input parameter ).
52 //
53 // Test variations:
54 // - multi_view tests check if density map also works when VK_KHR_multiview extension is in use
55 // - render_copy tests check if it's possible to copy results using input attachment descriptor ( this simulates deferred rendering behaviour )
56 // - non_divisible_density_size tests check if subsampled images work when its dimension is not divisible by minFragmentDensityTexelSize
57 // - N_samples tests check if multisampling works with VK_EXT_fragment_density_map extension
58 // - static_* tests use density map loaded from CPU during vkCmdBeginRenderPass.
59 // - dynamic_* tests use density map rendered on a GPU in a separate render pass
60 // - deffered_* tests use density map loaded from CPU during VkEndCommandBuffer.
61 // - *_nonsubsampled tests check if it's possible to use nonsubsampled images instead of subsampled ones
62 
63 // There are 3 render passes performed during most of the tests:
64 //  - render pass that produces density map ( this rp is skipped when density map is static )
65 //  - render pass that produces subsampled image using density map and eventually copies results to different image ( render_copy )
66 //  - render pass that copies subsampled image to traditional image using sampler with VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT flag.
67 //    ( because subsampled images cannot be retrieved to CPU in any other way ).
68 // There are few tests that use additional subpass that resamples subsampled image using diferent density map.
69 
70 // Code of FragmentDensityMapTestInstance is also used to test subsampledLoads, subsampledCoarseReconstructionEarlyAccess,
71 // maxDescriptorSetSubsampledSamplers properties.
72 
73 // set value of DRY_RUN_WITHOUT_FDM_EXTENSION to 1 for dummy run hat checks the correctness of the code without using VK_EXT_fragment_density_map extension
74 #define DRY_RUN_WITHOUT_FDM_EXTENSION 0
75 
76 namespace vkt
77 {
78 
79 namespace renderpass
80 {
81 
82 using namespace vk;
83 
84 namespace
85 {
86 
87 struct TestParams
88 {
89 	bool					dynamicDensityMap;
90 	bool					deferredDensityMap;
91 	bool					nonSubsampledImages;
92 	bool					subsampledLoads;
93 	bool					coarseReconstruction;
94 	deUint32				samplersCount;
95 	deUint32				viewCount;
96 	bool					makeCopy;
97 	float					renderMultiplier;
98 	VkSampleCountFlagBits	colorSamples;
99 	tcu::UVec2				fragmentArea;
100 	tcu::UVec2				densityMapSize;
101 	VkFormat				densityMapFormat;
102 };
103 
104 struct Vertex4RGBA
105 {
106 	tcu::Vec4	position;
107 	tcu::Vec4	uv;
108 	tcu::Vec4	color;
109 };
110 
111 de::SharedPtr<Move<vk::VkDevice>>	g_singletonDevice;
112 
removeExtensions(const std::vector<std::string> & a,const std::vector<const char * > & b)113 static std::vector<std::string> removeExtensions (const std::vector<std::string>& a, const std::vector<const char*>& b)
114 {
115 	std::vector<std::string>	res;
116 	std::set<std::string>		removeExts	(b.begin(), b.end());
117 
118 	for (std::vector<std::string>::const_iterator aIter = a.begin(); aIter != a.end(); ++aIter)
119 	{
120 		if (!de::contains(removeExts, *aIter))
121 			res.push_back(*aIter);
122 	}
123 
124 	return res;
125 }
126 
getDevice(Context & context)127 VkDevice getDevice(Context& context)
128 {
129 	if (!g_singletonDevice)
130 	{
131 		const float queuePriority = 1.0f;
132 
133 		// Create a universal queue that supports graphics and compute
134 		const VkDeviceQueueCreateInfo	queueParams =
135 		{
136 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
137 			DE_NULL,									// const void*					pNext;
138 			0u,											// VkDeviceQueueCreateFlags		flags;
139 			context.getUniversalQueueFamilyIndex(),		// deUint32						queueFamilyIndex;
140 			1u,											// deUint32						queueCount;
141 			&queuePriority								// const float*					pQueuePriorities;
142 		};
143 
144 		// \note Extensions in core are not explicitly enabled even though
145 		//		 they are in the extension list advertised to tests.
146 		std::vector<const char*>	extensionPtrs;
147 		std::vector<const char*>	coreExtensions;
148 		getCoreDeviceExtensions(context.getUsedApiVersion(), coreExtensions);
149 		std::vector<std::string>	nonCoreExtensions(removeExtensions(context.getDeviceExtensions(), coreExtensions));
150 
151 		extensionPtrs.resize(nonCoreExtensions.size());
152 
153 		for (size_t ndx = 0; ndx < nonCoreExtensions.size(); ++ndx)
154 			extensionPtrs[ndx] = nonCoreExtensions[ndx].c_str();
155 
156 		VkPhysicalDeviceFragmentDensityMapFeaturesEXT	fragmentDensityMapFeatures	= initVulkanStructure();
157 		VkPhysicalDeviceFragmentDensityMap2FeaturesEXT	fragmentDensityMap2Features	= initVulkanStructure(&fragmentDensityMapFeatures);
158 		VkPhysicalDeviceFeatures2						features2					= initVulkanStructure(&fragmentDensityMap2Features);
159 
160 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
161 		const VkPhysicalDeviceFeatures2 & feature2ptr = context.getDeviceFeatures2();
162 
163 		const VkDeviceCreateInfo					deviceCreateInfo =
164 		{
165 			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,							//sType;
166 			&feature2ptr,													//pNext;
167 			(VkDeviceCreateFlags)0u,										//flags
168 			1,																//queueRecordCount;
169 			&queueParams,													//pRequestedQueues;
170 			0,																//layerCount;
171 			DE_NULL,														//ppEnabledLayerNames;
172 			(deUint32)extensionPtrs.size(),			// deUint32				enabledExtensionCount;
173 			(extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]),			// const char* const*				ppEnabledExtensionNames;
174 			DE_NULL,														//pEnabledFeatures;
175 		};
176 
177 		Move<VkDevice> device = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceCreateInfo);
178 		g_singletonDevice = de::SharedPtr<Move<VkDevice>>(new Move<VkDevice>(device));
179 	}
180 
181 	return g_singletonDevice->get();
182 }
183 
createFullscreenMesh(deUint32 viewCount,tcu::Vec2 redGradient,tcu::Vec2 greenGradient)184 std::vector<Vertex4RGBA> createFullscreenMesh(deUint32 viewCount, tcu::Vec2 redGradient, tcu::Vec2 greenGradient)
185 {
186 	DE_ASSERT(viewCount > 0);
187 
188 	const auto&		r		= redGradient;
189 	const auto&		g		= greenGradient;
190 	const float		step	= 2.0f / static_cast<float>(viewCount);
191 	float			xStart	= -1.0f;
192 
193 	std::vector<Vertex4RGBA> resultMesh;
194 	for (deUint32 viewIndex = 0; viewIndex < viewCount ; ++viewIndex)
195 	{
196 		const float		fIndex		= static_cast<float>(viewIndex);
197 		const deUint32	nextIndex	= viewIndex + 1;
198 		const float		xEnd		= (nextIndex == viewCount) ? 1.0f : (-1.0f + step * static_cast<float>(nextIndex));
199 
200 		// quad vertex							position						uv								color
201 		const Vertex4RGBA lowerLeftVertex	= { { xStart,  1.0f, 0.0f, 1.0f },	{ 0.0f, 1.0f, fIndex, 1.0f },	{ r.x(), g.y(), 0.0f, 1.0f } };
202 		const Vertex4RGBA upperLeftVertex	= { { xStart, -1.0f, 0.0f, 1.0f },	{ 0.0f, 0.0f, fIndex, 1.0f },	{ r.x(), g.x(), 0.0f, 1.0f } };
203 		const Vertex4RGBA lowerRightVertex	= { {   xEnd,  1.0f, 0.0f, 1.0f },	{ 1.0f, 1.0f, fIndex, 1.0f },	{ r.y(), g.y(), 0.0f, 1.0f } };
204 		const Vertex4RGBA upperRightVertex	= { {   xEnd, -1.0f, 0.0f, 1.0f },	{ 1.0f, 0.0f, fIndex, 1.0f },	{ r.y(), g.x(), 0.0f, 1.0f } };
205 
206 		const std::vector<Vertex4RGBA> viewData
207 		{
208 			lowerLeftVertex, lowerRightVertex, upperLeftVertex,
209 			upperLeftVertex, lowerRightVertex, upperRightVertex
210 		};
211 
212 		resultMesh.insert(resultMesh.end(), viewData.begin(), viewData.end());
213 		xStart = xEnd;
214 	}
215 
216 	return resultMesh;
217 }
218 
219 template <typename T>
createVertexBuffer(const DeviceInterface & vk,VkDevice vkDevice,const deUint32 & queueFamilyIndex,SimpleAllocator & memAlloc,const std::vector<T> & vertices,Move<VkBuffer> & vertexBuffer,de::MovePtr<Allocation> & vertexAlloc)220 void createVertexBuffer(const DeviceInterface&		vk,
221 						VkDevice					vkDevice,
222 						const deUint32&				queueFamilyIndex,
223 						SimpleAllocator&			memAlloc,
224 						const std::vector<T>&		vertices,
225 						Move<VkBuffer>&				vertexBuffer,
226 						de::MovePtr<Allocation>&	vertexAlloc)
227 {
228 	const VkBufferCreateInfo vertexBufferParams =
229 	{
230 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,			// VkStructureType		sType;
231 		DE_NULL,										// const void*			pNext;
232 		0u,												// VkBufferCreateFlags	flags;
233 		(VkDeviceSize)(sizeof(T) * vertices.size()),	// VkDeviceSize			size;
234 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,				// VkBufferUsageFlags	usage;
235 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode		sharingMode;
236 		1u,												// deUint32				queueFamilyIndexCount;
237 		&queueFamilyIndex								// const deUint32*		pQueueFamilyIndices;
238 	};
239 
240 	vertexBuffer	= createBuffer(vk, vkDevice, &vertexBufferParams);
241 	vertexAlloc		= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
242 	VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexAlloc->getMemory(), vertexAlloc->getOffset()));
243 
244 	// Upload vertex data
245 	deMemcpy(vertexAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(T));
246 	flushAlloc(vk, vkDevice, *vertexAlloc);
247 }
248 
prepareImageAndImageView(const DeviceInterface & vk,VkDevice vkDevice,SimpleAllocator & memAlloc,VkImageCreateFlags imageCreateFlags,VkFormat format,VkExtent3D extent,deUint32 arrayLayers,VkSampleCountFlagBits samples,VkImageUsageFlags usage,deUint32 queueFamilyIndex,VkImageViewCreateFlags viewFlags,VkImageViewType viewType,const VkComponentMapping & channels,const VkImageSubresourceRange & subresourceRange,Move<VkImage> & image,de::MovePtr<Allocation> & imageAlloc,Move<VkImageView> & imageView)249 void prepareImageAndImageView	(const DeviceInterface&			vk,
250 								 VkDevice						vkDevice,
251 								 SimpleAllocator&				memAlloc,
252 								 VkImageCreateFlags				imageCreateFlags,
253 								 VkFormat						format,
254 								 VkExtent3D						extent,
255 								 deUint32						arrayLayers,
256 								 VkSampleCountFlagBits			samples,
257 								 VkImageUsageFlags				usage,
258 								 deUint32						queueFamilyIndex,
259 								 VkImageViewCreateFlags			viewFlags,
260 								 VkImageViewType				viewType,
261 								 const VkComponentMapping&		channels,
262 								 const VkImageSubresourceRange&	subresourceRange,
263 								 Move<VkImage>&					image,
264 								 de::MovePtr<Allocation>&		imageAlloc,
265 								 Move<VkImageView>&				imageView)
266 {
267 	const VkImageCreateInfo imageCreateInfo
268 	{
269 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
270 		DE_NULL,									// const void*				pNext;
271 		imageCreateFlags,							// VkImageCreateFlags		flags;
272 		VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
273 		format,										// VkFormat					format;
274 		extent,										// VkExtent3D				extent;
275 		1u,											// deUint32					mipLevels;
276 		arrayLayers,								// deUint32					arrayLayers;
277 		samples,									// VkSampleCountFlagBits	samples;
278 		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
279 		usage,										// VkImageUsageFlags		usage;
280 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
281 		1u,											// deUint32					queueFamilyIndexCount;
282 		&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
283 		VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
284 	};
285 
286 	image = createImage(vk, vkDevice, &imageCreateInfo);
287 
288 	// Allocate and bind color image memory
289 	imageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any);
290 	VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageAlloc->getMemory(), imageAlloc->getOffset()));
291 
292 	// create image view for subsampled image
293 	const VkImageViewCreateInfo imageViewCreateInfo =
294 	{
295 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
296 		DE_NULL,									// const void*				pNext;
297 		viewFlags,									// VkImageViewCreateFlags	flags;
298 		*image,										// VkImage					image;
299 		viewType,									// VkImageViewType			viewType;
300 		format,										// VkFormat					format;
301 		channels,									// VkChannelMapping			channels;
302 		subresourceRange							// VkImageSubresourceRange	subresourceRange;
303 	};
304 
305 	imageView = createImageView(vk, vkDevice, &imageViewCreateInfo);
306 }
307 
createRenderPassProduceDynamicDensityMap(const DeviceInterface & vk,VkDevice vkDevice,deUint32 viewMask,const TestParams & testParams)308 Move<VkRenderPass> createRenderPassProduceDynamicDensityMap(const DeviceInterface&	vk,
309 															VkDevice				vkDevice,
310 															deUint32				viewMask,
311 															const TestParams&		testParams)
312 {
313 	DE_ASSERT(testParams.dynamicDensityMap);
314 
315 	typedef AttachmentDescription2	AttachmentDesc;
316 	typedef AttachmentReference2	AttachmentRef;
317 	typedef SubpassDescription2		SubpassDesc;
318 	typedef SubpassDependency2		SubpassDep;
319 	typedef RenderPassCreateInfo2	RenderPassCreateInfo;
320 
321 	std::vector<AttachmentDesc> attachmentDescriptions
322 	{
323 		{
324 			DE_NULL,															// const void*						pNext
325 			(VkAttachmentDescriptionFlags)0,									// VkAttachmentDescriptionFlags		flags
326 			testParams.densityMapFormat,										// VkFormat							format
327 			VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagBits			samples
328 			VK_ATTACHMENT_LOAD_OP_CLEAR,										// VkAttachmentLoadOp				loadOp
329 			VK_ATTACHMENT_STORE_OP_STORE,										// VkAttachmentStoreOp				storeOp
330 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,									// VkAttachmentLoadOp				stencilLoadOp
331 			VK_ATTACHMENT_STORE_OP_DONT_CARE,									// VkAttachmentStoreOp				stencilStoreOp
332 			VK_IMAGE_LAYOUT_UNDEFINED,											// VkImageLayout					initialLayout
333 #if DRY_RUN_WITHOUT_FDM_EXTENSION
334 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL							// VkImageLayout					finalLayout
335 #else
336 			VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT					// VkImageLayout					finalLayout
337 #endif
338 		}
339 	};
340 
341 	std::vector<AttachmentRef> colorAttachmentRefs
342 	{
343 		{ DE_NULL, 0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }
344 	};
345 
346 	std::vector<SubpassDesc> subpassDescriptions
347 	{
348 		{
349 			DE_NULL,
350 			(VkSubpassDescriptionFlags)0,										// VkSubpassDescriptionFlags		flags
351 			VK_PIPELINE_BIND_POINT_GRAPHICS,									// VkPipelineBindPoint				pipelineBindPoint
352 			viewMask,															// deUint32							viewMask
353 			0u,																	// deUint32							inputAttachmentCount
354 			DE_NULL,															// const VkAttachmentReference*		pInputAttachments
355 			static_cast<deUint32>(colorAttachmentRefs.size()),					// deUint32							colorAttachmentCount
356 			colorAttachmentRefs.data(),											// const VkAttachmentReference*		pColorAttachments
357 			DE_NULL,															// const VkAttachmentReference*		pResolveAttachments
358 			DE_NULL,															// const VkAttachmentReference*		pDepthStencilAttachment
359 			0u,																	// deUint32							preserveAttachmentCount
360 			DE_NULL																// const deUint32*					pPreserveAttachments
361 		}
362 	};
363 
364 	std::vector<SubpassDep> subpassDependencies
365 	{
366 		{
367 			DE_NULL,															// const void*				pNext
368 			0u,																	// uint32_t					srcSubpass
369 			VK_SUBPASS_EXTERNAL,												// uint32_t					dstSubpass
370 #if DRY_RUN_WITHOUT_FDM_EXTENSION
371 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,						// VkPipelineStageFlags		srcStageMask
372 			VK_PIPELINE_STAGE_TRANSFER_BIT,										// VkPipelineStageFlags		dstStageMask
373 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,								// VkAccessFlags			srcAccessMask
374 			VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,								// VkAccessFlags			dstAccessMask
375 #else
376 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,						// VkPipelineStageFlags		srcStageMask
377 			VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT,					// VkPipelineStageFlags		dstStageMask
378 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,								// VkAccessFlags			srcAccessMask
379 			VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT,						// VkAccessFlags			dstAccessMask
380 #endif
381 			VK_DEPENDENCY_BY_REGION_BIT,										// VkDependencyFlags		dependencyFlags
382 			0u																	// deInt32					viewOffset
383 		}
384 	};
385 
386 	const RenderPassCreateInfo renderPassInfo(
387 		DE_NULL,																// const void*						pNext
388 		(VkRenderPassCreateFlags)0,												// VkRenderPassCreateFlags			flags
389 		static_cast<deUint32>(attachmentDescriptions.size()),					// deUint32							attachmentCount
390 		attachmentDescriptions.data(),											// const VkAttachmentDescription*	pAttachments
391 		static_cast<deUint32>(subpassDescriptions.size()),						// deUint32							subpassCount
392 		subpassDescriptions.data(),												// const VkSubpassDescription*		pSubpasses
393 		static_cast<deUint32>(subpassDependencies.size()),						// deUint32							dependencyCount
394 		subpassDependencies.empty() ? DE_NULL : subpassDependencies.data(),		// const VkSubpassDependency*		pDependencies
395 		0u,																		// deUint32							correlatedViewMaskCount
396 		DE_NULL																	// const deUint32*					pCorrelatedViewMasks
397 	);
398 
399 	return renderPassInfo.createRenderPass(vk, vkDevice);
400 }
401 
createRenderPassProduceSubsampledImage(const DeviceInterface & vk,VkDevice vkDevice,deUint32 viewMask,bool makeCopySubpass,bool resampleSubsampled,const TestParams & testParams)402 Move<VkRenderPass> createRenderPassProduceSubsampledImage(const DeviceInterface&	vk,
403 														  VkDevice					vkDevice,
404 														  deUint32					viewMask,
405 														  bool						makeCopySubpass,
406 														  bool						resampleSubsampled,
407 														  const TestParams&			testParams)
408 {
409 	typedef AttachmentDescription2	AttachmentDesc;
410 	typedef AttachmentReference2	AttachmentRef;
411 	typedef SubpassDescription2		SubpassDesc;
412 	typedef SubpassDependency2		SubpassDep;
413 	typedef RenderPassCreateInfo2	RenderPassCreateInfo;
414 
415 	const void* constNullPtr				= DE_NULL;
416 	deUint32	multisampleAttachmentIndex	= 0;
417 	deUint32	copyAttachmentIndex			= 0;
418 	deUint32	densityMapAttachmentIndex	= 0;
419 
420 	// add color image
421 	VkAttachmentLoadOp			loadOp = resampleSubsampled ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
422 	std::vector<AttachmentDesc> attachmentDescriptions
423 	{
424 		// Output color attachment
425 		{
426 			DE_NULL,															// const void*						pNext
427 			(VkAttachmentDescriptionFlags)0,									// VkAttachmentDescriptionFlags		flags
428 			VK_FORMAT_R8G8B8A8_UNORM,											// VkFormat							format
429 			testParams.colorSamples,											// VkSampleCountFlagBits			samples
430 			loadOp,																// VkAttachmentLoadOp				loadOp
431 			VK_ATTACHMENT_STORE_OP_STORE,										// VkAttachmentStoreOp				storeOp
432 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,									// VkAttachmentLoadOp				stencilLoadOp
433 			VK_ATTACHMENT_STORE_OP_DONT_CARE,									// VkAttachmentStoreOp				stencilStoreOp
434 			VK_IMAGE_LAYOUT_UNDEFINED,											// VkImageLayout					initialLayout
435 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL							// VkImageLayout					finalLayout
436 		}
437 	};
438 
439 	// add resolve image when we use more than one sample per fragment
440 	if (testParams.colorSamples != VK_SAMPLE_COUNT_1_BIT)
441 	{
442 		multisampleAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
443 		attachmentDescriptions.emplace_back(
444 			constNullPtr,														// const void*						pNext
445 			(VkAttachmentDescriptionFlags)0,									// VkAttachmentDescriptionFlags		flags
446 			VK_FORMAT_R8G8B8A8_UNORM,											// VkFormat							format
447 			VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagBits			samples
448 			VK_ATTACHMENT_LOAD_OP_CLEAR,										// VkAttachmentLoadOp				loadOp
449 			VK_ATTACHMENT_STORE_OP_STORE,										// VkAttachmentStoreOp				storeOp
450 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,									// VkAttachmentLoadOp				stencilLoadOp
451 			VK_ATTACHMENT_STORE_OP_DONT_CARE,									// VkAttachmentStoreOp				stencilStoreOp
452 			VK_IMAGE_LAYOUT_UNDEFINED,											// VkImageLayout					initialLayout
453 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL							// VkImageLayout					finalLayout
454 		);
455 	}
456 
457 	// add color image copy ( when render_copy is used )
458 	if (makeCopySubpass)
459 	{
460 		copyAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
461 		attachmentDescriptions.emplace_back(
462 			constNullPtr,														// const void*						pNext
463 			(VkAttachmentDescriptionFlags)0,									// VkAttachmentDescriptionFlags		flags
464 			VK_FORMAT_R8G8B8A8_UNORM,											// VkFormat							format
465 			testParams.colorSamples,											// VkSampleCountFlagBits			samples
466 			VK_ATTACHMENT_LOAD_OP_CLEAR,										// VkAttachmentLoadOp				loadOp
467 			VK_ATTACHMENT_STORE_OP_STORE,										// VkAttachmentStoreOp				storeOp
468 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,									// VkAttachmentLoadOp				stencilLoadOp
469 			VK_ATTACHMENT_STORE_OP_DONT_CARE,									// VkAttachmentStoreOp				stencilStoreOp
470 			VK_IMAGE_LAYOUT_UNDEFINED,											// VkImageLayout					initialLayout
471 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL							// VkImageLayout					finalLayout
472 		);
473 	}
474 
475 	// add density map
476 	densityMapAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
477 	attachmentDescriptions.emplace_back(
478 		constNullPtr,															// const void*						pNext
479 		(VkAttachmentDescriptionFlags)0,										// VkAttachmentDescriptionFlags		flags
480 		testParams.densityMapFormat,											// VkFormat							format
481 		VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits			samples
482 		VK_ATTACHMENT_LOAD_OP_LOAD,												// VkAttachmentLoadOp				loadOp
483 		VK_ATTACHMENT_STORE_OP_DONT_CARE,										// VkAttachmentStoreOp				storeOp
484 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,										// VkAttachmentLoadOp				stencilLoadOp
485 		VK_ATTACHMENT_STORE_OP_DONT_CARE,										// VkAttachmentStoreOp				stencilStoreOp
486 		VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT,						// VkImageLayout					initialLayout
487 		VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT						// VkImageLayout					finalLayout
488 	);
489 
490 	std::vector<AttachmentRef> colorAttachmentRefs0
491 	{
492 		{ DE_NULL, 0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }
493 	};
494 
495 	// for multisampled scenario we need to add resolve attachment
496 	// (for makeCopy scenario it is used in second subpass)
497 	AttachmentRef*	pResolveAttachments		= DE_NULL;
498 	AttachmentRef	resolveAttachmentRef
499 	{
500 		DE_NULL,
501 		multisampleAttachmentIndex,
502 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
503 		VK_IMAGE_ASPECT_COLOR_BIT
504 	};
505 	if (testParams.colorSamples != VK_SAMPLE_COUNT_1_BIT)
506 		pResolveAttachments = &resolveAttachmentRef;
507 
508 	std::vector<SubpassDesc> subpassDescriptions
509 	{
510 		{
511 			DE_NULL,
512 			(VkSubpassDescriptionFlags)0,							// VkSubpassDescriptionFlags	flags
513 			VK_PIPELINE_BIND_POINT_GRAPHICS,						// VkPipelineBindPoint			pipelineBindPoint
514 			viewMask,												// deUint32						viewMask
515 			0u,														// deUint32						inputAttachmentCount
516 			DE_NULL,												// const VkAttachmentReference*	pInputAttachments
517 			static_cast<deUint32>(colorAttachmentRefs0.size()),		// deUint32						colorAttachmentCount
518 			colorAttachmentRefs0.data(),							// const VkAttachmentReference*	pColorAttachments
519 			makeCopySubpass ? DE_NULL : pResolveAttachments,		// const VkAttachmentReference*	pResolveAttachments
520 			DE_NULL,												// const VkAttachmentReference*	pDepthStencilAttachment
521 			0u,														// deUint32						preserveAttachmentCount
522 			DE_NULL													// const deUint32*				pPreserveAttachments
523 		}
524 	};
525 
526 	std::vector<AttachmentRef>	inputAttachmentRefs1
527 	{
528 		{ DE_NULL, 0u, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }
529 	};
530 	std::vector<AttachmentRef>	colorAttachmentRefs1
531 	{
532 		{ DE_NULL, copyAttachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }
533 	};
534 	std::vector<SubpassDep>		subpassDependencies;
535 
536 	if (makeCopySubpass)
537 	{
538 		subpassDescriptions.push_back({
539 			DE_NULL,
540 			(VkSubpassDescriptionFlags)0,							// VkSubpassDescriptionFlags	flags
541 			VK_PIPELINE_BIND_POINT_GRAPHICS,						// VkPipelineBindPoint			pipelineBindPoint
542 			viewMask,												// deUint32						viewMask
543 			static_cast<deUint32>(inputAttachmentRefs1.size()),		// deUint32						inputAttachmentCount
544 			inputAttachmentRefs1.data(),							// const VkAttachmentReference*	pInputAttachments
545 			static_cast<deUint32>(colorAttachmentRefs1.size()),		// deUint32						colorAttachmentCount
546 			colorAttachmentRefs1.data(),							// const VkAttachmentReference*	pColorAttachments
547 			pResolveAttachments,									// const VkAttachmentReference*	pResolveAttachments
548 			DE_NULL,												// const VkAttachmentReference*	pDepthStencilAttachment
549 			0u,														// deUint32						preserveAttachmentCount
550 			DE_NULL													// const deUint32*				pPreserveAttachments
551 		});
552 
553 		VkDependencyFlags dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
554 		if (testParams.viewCount > 1)
555 			dependencyFlags |= VK_DEPENDENCY_VIEW_LOCAL_BIT;
556 
557 		subpassDependencies.emplace_back(
558 			constNullPtr,																// const void*				pNext
559 			0u,																			// uint32_t					srcSubpass
560 			1u,																			// uint32_t					dstSubpass
561 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,								// VkPipelineStageFlags		srcStageMask
562 			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,										// VkPipelineStageFlags		dstStageMask
563 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,										// VkAccessFlags			srcAccessMask
564 			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,										// VkAccessFlags			dstAccessMask
565 			dependencyFlags,															// VkDependencyFlags		dependencyFlags
566 			0u																			// deInt32					viewOffset
567 		);
568 	}
569 
570 	VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
571 
572 	// for coarse reconstruction we need to put barrier on vertex stage
573 	if (testParams.coarseReconstruction)
574 		dstStageMask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
575 
576 	subpassDependencies.emplace_back(
577 		constNullPtr,																	// const void*				pNext
578 		static_cast<deUint32>(subpassDescriptions.size())-1u,							// uint32_t					srcSubpass
579 		VK_SUBPASS_EXTERNAL,															// uint32_t					dstSubpass
580 		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,									// VkPipelineStageFlags		srcStageMask
581 		dstStageMask,																	// VkPipelineStageFlags		dstStageMask
582 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,											// VkAccessFlags			srcAccessMask
583 		VK_ACCESS_SHADER_READ_BIT,														// VkAccessFlags			dstAccessMask
584 		VK_DEPENDENCY_BY_REGION_BIT,													// VkDependencyFlags		dependencyFlags
585 		0u																				// deInt32					viewOffset
586 	);
587 
588 	VkRenderPassFragmentDensityMapCreateInfoEXT renderPassFragmentDensityMap =
589 	{
590 		VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT,
591 		DE_NULL,
592 		{ densityMapAttachmentIndex, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT }
593 	};
594 
595 	void* renderPassInfoPNext = (void*)&renderPassFragmentDensityMap;
596 
597 #if DRY_RUN_WITHOUT_FDM_EXTENSION
598 	// density map description is at the end - pop it from vector
599 	attachmentDescriptions.pop_back();
600 	renderPassInfoPNext = DE_NULL;
601 #endif
602 
603 	const RenderPassCreateInfo	renderPassInfo(
604 		renderPassInfoPNext,														// const void*						pNext
605 		(VkRenderPassCreateFlags)0,													// VkRenderPassCreateFlags			flags
606 		static_cast<deUint32>(attachmentDescriptions.size()),						// deUint32							attachmentCount
607 		attachmentDescriptions.data(),												// const VkAttachmentDescription*	pAttachments
608 		static_cast<deUint32>(subpassDescriptions.size()),							// deUint32							subpassCount
609 		subpassDescriptions.data(),													// const VkSubpassDescription*		pSubpasses
610 		static_cast<deUint32>(subpassDependencies.size()),							// deUint32							dependencyCount
611 		subpassDependencies.data(),													// const VkSubpassDependency*		pDependencies
612 		0u,																			// deUint32							correlatedViewMaskCount
613 		DE_NULL																		// const deUint32*					pCorrelatedViewMasks
614 	);
615 
616 	return renderPassInfo.createRenderPass(vk, vkDevice);
617 }
618 
createRenderPassOutputSubsampledImage(const DeviceInterface & vk,VkDevice vkDevice)619 Move<VkRenderPass> createRenderPassOutputSubsampledImage(const DeviceInterface&	vk,
620 														 VkDevice				vkDevice)
621 {
622 	typedef AttachmentDescription2	AttachmentDesc;
623 	typedef AttachmentReference2	AttachmentRef;
624 	typedef SubpassDescription2		SubpassDesc;
625 	typedef RenderPassCreateInfo2	RenderPassCreateInfo;
626 
627 	// copy subsampled image to ordinary image - you cannot retrieve subsampled image to CPU in any way.
628 	// You must first convert it into plain image through rendering
629 	std::vector<AttachmentDesc> attachmentDescriptions =
630 	{
631 		// output attachment
632 		{
633 			DE_NULL,											// const void*						pNext
634 			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags
635 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat							format
636 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples
637 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp
638 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp
639 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp
640 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp
641 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout
642 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout
643 		},
644 	};
645 
646 	std::vector<AttachmentRef> colorAttachmentRefs
647 	{
648 		{ DE_NULL, 0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }
649 	};
650 
651 	std::vector<SubpassDesc> subpassDescriptions =
652 	{
653 		{
654 			DE_NULL,
655 			(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags
656 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint
657 			0u,													// deUint32							viewMask
658 			0u,													// deUint32							inputAttachmentCount
659 			DE_NULL,											// const VkAttachmentReference*		pInputAttachments
660 			static_cast<deUint32>(colorAttachmentRefs.size()),	// deUint32							colorAttachmentCount
661 			colorAttachmentRefs.data(),							// const VkAttachmentReference*		pColorAttachments
662 			DE_NULL,											// const VkAttachmentReference*		pResolveAttachments
663 			DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment
664 			0u,													// deUint32							preserveAttachmentCount
665 			DE_NULL												// const deUint32*					pPreserveAttachments
666 		}
667 	};
668 
669 	const RenderPassCreateInfo	renderPassInfo(
670 		DE_NULL,												// const void*						pNext
671 		(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags
672 		static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount
673 		attachmentDescriptions.data(),							// const VkAttachmentDescription*	pAttachments
674 		static_cast<deUint32>(subpassDescriptions.size()),		// deUint32							subpassCount
675 		subpassDescriptions.data(),								// const VkSubpassDescription*		pSubpasses
676 		0,														// deUint32							dependencyCount
677 		DE_NULL,												// const VkSubpassDependency*		pDependencies
678 		0u,														// deUint32							correlatedViewMaskCount
679 		DE_NULL													// const deUint32*					pCorrelatedViewMasks
680 	);
681 
682 	return renderPassInfo.createRenderPass(vk, vkDevice);
683 }
684 
createFrameBuffer(const DeviceInterface & vk,VkDevice vkDevice,VkRenderPass renderPass,VkExtent3D size,const std::vector<VkImageView> & imageViews)685 Move<VkFramebuffer> createFrameBuffer( const DeviceInterface& vk, VkDevice vkDevice, VkRenderPass renderPass, VkExtent3D size, const std::vector<VkImageView>& imageViews)
686 {
687 	const VkFramebufferCreateInfo framebufferParams =
688 	{
689 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
690 		DE_NULL,									// const void*				pNext;
691 		0u,											// VkFramebufferCreateFlags	flags;
692 		renderPass,									// VkRenderPass				renderPass;
693 		static_cast<deUint32>(imageViews.size()),	// deUint32					attachmentCount;
694 		imageViews.data(),							// const VkImageView*		pAttachments;
695 		size.width,									// deUint32					width;
696 		size.height,								// deUint32					height;
697 		1u											// deUint32					layers;
698 	};
699 
700 	return createFramebuffer(vk, vkDevice, &framebufferParams);
701 }
702 
copyBufferToImage(const DeviceInterface & vk,VkDevice device,VkQueue queue,deUint32 queueFamilyIndex,const VkBuffer & buffer,VkDeviceSize bufferSize,const VkExtent3D & imageSize,deUint32 arrayLayers,VkImage destImage)703 void copyBufferToImage(const DeviceInterface&					vk,
704 					   VkDevice									device,
705 					   VkQueue									queue,
706 					   deUint32									queueFamilyIndex,
707 					   const VkBuffer&							buffer,
708 					   VkDeviceSize								bufferSize,
709 					   const VkExtent3D&						imageSize,
710 					   deUint32									arrayLayers,
711 					   VkImage									destImage)
712 {
713 	Move<VkCommandPool>		cmdPool					= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
714 	Move<VkCommandBuffer>	cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
715 	Move<VkFence>			fence					= createFence(vk, device);
716 	VkImageLayout			destImageLayout			= VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT;
717 	VkPipelineStageFlags	destImageDstStageFlags	= VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT;
718 	VkAccessFlags			finalAccessMask			= VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT;
719 
720 #if DRY_RUN_WITHOUT_FDM_EXTENSION
721 	destImageLayout			= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
722 	destImageDstStageFlags	= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
723 	finalAccessMask			= VK_ACCESS_SHADER_READ_BIT;
724 #endif
725 
726 	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
727 	{
728 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,		// VkStructureType					sType;
729 		DE_NULL,											// const void*						pNext;
730 		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,		// VkCommandBufferUsageFlags		flags;
731 		(const VkCommandBufferInheritanceInfo*)DE_NULL,
732 	};
733 
734 	const VkBufferImageCopy copyRegion =
735 	{
736 		0,													// VkDeviceSize					bufferOffset
737 		0,													// deUint32						bufferRowLength
738 		0,													// deUint32						bufferImageHeight
739 		{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, arrayLayers },	// VkImageSubresourceLayers		imageSubresource
740 		{ 0, 0, 0 },										// VkOffset3D					imageOffset
741 		imageSize											// VkExtent3D					imageExtent
742 	};
743 
744 	// Barriers for copying buffer to image
745 	const VkBufferMemoryBarrier preBufferBarrier = makeBufferMemoryBarrier(
746 		VK_ACCESS_HOST_WRITE_BIT,							// VkAccessFlags	srcAccessMask;
747 		VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags	dstAccessMask;
748 		buffer,												// VkBuffer			buffer;
749 		0u,													// VkDeviceSize		offset;
750 		bufferSize											// VkDeviceSize		size;
751 	);
752 
753 	const VkImageSubresourceRange subresourceRange
754 	{														// VkImageSubresourceRange	subresourceRange;
755 		VK_IMAGE_ASPECT_COLOR_BIT,							// VkImageAspectFlags		aspect;
756 		0u,													// deUint32					baseMipLevel;
757 		1u,													// deUint32					mipLevels;
758 		0u,													// deUint32					baseArraySlice;
759 		arrayLayers											// deUint32					arraySize;
760 	};
761 
762 	const VkImageMemoryBarrier preImageBarrier = makeImageMemoryBarrier(
763 		0u,													// VkAccessFlags			srcAccessMask;
764 		VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			dstAccessMask;
765 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
766 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			newLayout;
767 		destImage,											// VkImage					image;
768 		subresourceRange									// VkImageSubresourceRange	subresourceRange;
769 	);
770 
771 	const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(
772 		VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			srcAccessMask;
773 		finalAccessMask,									// VkAccessFlags			dstAccessMask;
774 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			oldLayout;
775 		destImageLayout,									// VkImageLayout			newLayout;
776 		destImage,											// VkImage					image;
777 		subresourceRange									// VkImageSubresourceRange	subresourceRange;
778 	);
779 
780 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
781 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier);
782 	vk.cmdCopyBufferToImage(*cmdBuffer, buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
783 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, destImageDstStageFlags, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
784 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
785 
786 	const VkPipelineStageFlags pipelineStageFlags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
787 
788 	const VkSubmitInfo submitInfo =
789 	{
790 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
791 		DE_NULL,						// const void*					pNext;
792 		0u,								// deUint32						waitSemaphoreCount;
793 		DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
794 		&pipelineStageFlags,			// const VkPipelineStageFlags*	pWaitDstStageMask;
795 		1u,								// deUint32						commandBufferCount;
796 		&cmdBuffer.get(),				// const VkCommandBuffer*		pCommandBuffers;
797 		0u,								// deUint32						signalSemaphoreCount;
798 		DE_NULL							// const VkSemaphore*			pSignalSemaphores;
799 	};
800 
801 	try
802 	{
803 		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
804 		VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull) /* infinity */));
805 	}
806 	catch (...)
807 	{
808 		VK_CHECK(vk.deviceWaitIdle(device));
809 		throw;
810 	}
811 }
812 
813 class FragmentDensityMapTest : public vkt::TestCase
814 {
815 public:
816 							FragmentDensityMapTest	(tcu::TestContext&	testContext,
817 													 const std::string&	name,
818 													 const std::string&	description,
819 													 const TestParams&	testParams);
820 	virtual void			initPrograms			(SourceCollections&	sourceCollections) const;
821 	virtual TestInstance*	createInstance			(Context&			context) const;
822 	virtual void			checkSupport			(Context&			context) const;
823 
824 private:
825 	const TestParams		m_testParams;
826 };
827 
828 class FragmentDensityMapTestInstance : public vkt::TestInstance
829 {
830 public:
831 									FragmentDensityMapTestInstance	(Context&			context,
832 																	 const TestParams&	testParams);
833 	virtual tcu::TestStatus			iterate							(void);
834 
835 private:
836 
837 	tcu::TestStatus					verifyImage						(void);
838 
839 private:
840 
841 	typedef de::SharedPtr<Unique<VkSampler> >	VkSamplerSp;
842 	typedef de::SharedPtr<Unique<VkImage> >		VkImageSp;
843 	typedef de::SharedPtr<Allocation>			AllocationSp;
844 	typedef de::SharedPtr<Unique<VkImageView> >	VkImageViewSp;
845 
846 	TestParams						m_testParams;
847 	tcu::UVec2						m_renderSize;
848 	tcu::Vec2						m_densityValue;
849 	deUint32						m_viewMask;
850 
851 	Move<VkCommandPool>				m_cmdPool;
852 
853 	std::vector<VkImageSp>			m_densityMapImages;
854 	std::vector<AllocationSp>		m_densityMapImageAllocs;
855 	std::vector<VkImageViewSp>		m_densityMapImageViews;
856 
857 	Move<VkImage>					m_colorImage;
858 	de::MovePtr<Allocation>			m_colorImageAlloc;
859 	Move<VkImageView>				m_colorImageView;
860 
861 	Move<VkImage>					m_colorCopyImage;
862 	de::MovePtr<Allocation>			m_colorCopyImageAlloc;
863 	Move<VkImageView>				m_colorCopyImageView;
864 
865 	Move<VkImage>					m_colorResolvedImage;
866 	de::MovePtr<Allocation>			m_colorResolvedImageAlloc;
867 	Move<VkImageView>				m_colorResolvedImageView;
868 
869 	Move<VkImage>					m_outputImage;
870 	de::MovePtr<Allocation>			m_outputImageAlloc;
871 	Move<VkImageView>				m_outputImageView;
872 
873 	std::vector<VkSamplerSp>		m_colorSamplers;
874 
875 	Move<VkRenderPass>				m_renderPassProduceDynamicDensityMap;
876 	Move<VkRenderPass>				m_renderPassProduceSubsampledImage;
877 	Move<VkRenderPass>				m_renderPassUpdateSubsampledImage;
878 	Move<VkRenderPass>				m_renderPassOutputSubsampledImage;
879 	Move<VkFramebuffer>				m_framebufferProduceDynamicDensityMap;
880 	Move<VkFramebuffer>				m_framebufferProduceSubsampledImage;
881 	Move<VkFramebuffer>				m_framebufferUpdateSubsampledImage;
882 	Move<VkFramebuffer>				m_framebufferOutputSubsampledImage;
883 
884 	Move<VkDescriptorSetLayout>		m_descriptorSetLayoutProduceSubsampled;
885 
886 	Move<VkDescriptorSetLayout>		m_descriptorSetLayoutOperateOnSubsampledImage;
887 	Move<VkDescriptorPool>			m_descriptorPoolOperateOnSubsampledImage;
888 	Move<VkDescriptorSet>			m_descriptorSetOperateOnSubsampledImage;
889 
890 	Move<VkDescriptorSetLayout>		m_descriptorSetLayoutOutputSubsampledImage;
891 	Move<VkDescriptorPool>			m_descriptorPoolOutputSubsampledImage;
892 	Move<VkDescriptorSet>			m_descriptorSetOutputSubsampledImage;
893 
894 	Move<VkShaderModule>			m_vertexCommonShaderModule;
895 	Move<VkShaderModule>			m_fragmentShaderModuleProduceSubsampledImage;
896 	Move<VkShaderModule>			m_fragmentShaderModuleCopySubsampledImage;
897 	Move<VkShaderModule>			m_fragmentShaderModuleUpdateSubsampledImage;
898 	Move<VkShaderModule>			m_fragmentShaderModuleOutputSubsampledImage;
899 
900 	std::vector<Vertex4RGBA>		m_verticesDDM;
901 	Move<VkBuffer>					m_vertexBufferDDM;
902 	de::MovePtr<Allocation>			m_vertexBufferAllocDDM;
903 
904 	std::vector<Vertex4RGBA>		m_vertices;
905 	Move<VkBuffer>					m_vertexBuffer;
906 	de::MovePtr<Allocation>			m_vertexBufferAlloc;
907 
908 	std::vector<Vertex4RGBA>		m_verticesOutput;
909 	Move<VkBuffer>					m_vertexBufferOutput;
910 	de::MovePtr<Allocation>			m_vertexBufferOutputAlloc;
911 
912 	Move<VkPipelineLayout>			m_pipelineLayoutNoDescriptors;
913 	Move<VkPipelineLayout>			m_pipelineLayoutOperateOnSubsampledImage;
914 	Move<VkPipelineLayout>			m_pipelineLayoutOutputSubsampledImage;
915 	Move<VkPipeline>				m_graphicsPipelineProduceDynamicDensityMap;
916 	Move<VkPipeline>				m_graphicsPipelineProduceSubsampledImage;
917 	Move<VkPipeline>				m_graphicsPipelineCopySubsampledImage;
918 	Move<VkPipeline>				m_graphicsPipelineUpdateSubsampledImage;
919 	Move<VkPipeline>				m_graphicsPipelineOutputSubsampledImage;
920 
921 	Move<VkCommandBuffer>			m_cmdBuffer;
922 };
923 
FragmentDensityMapTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & testParams)924 FragmentDensityMapTest::FragmentDensityMapTest (tcu::TestContext&	testContext,
925 												const std::string&	name,
926 												const std::string&	description,
927 												const TestParams&	testParams)
928 	: vkt::TestCase	(testContext, name, description)
929 	, m_testParams	(testParams)
930 {
931 	DE_ASSERT(testParams.samplersCount > 0);
932 }
933 
initPrograms(SourceCollections & sourceCollections) const934 void FragmentDensityMapTest::initPrograms(SourceCollections& sourceCollections) const
935 {
936 	sourceCollections.glslSources.add("vert") << glu::VertexSource(
937 		"#version 450\n"
938 		"#extension GL_EXT_multiview : enable\n"
939 		"layout(location = 0) in  vec4 inPosition;\n"
940 		"layout(location = 1) in  vec4 inUV;\n"
941 		"layout(location = 2) in  vec4 inColor;\n"
942 		"layout(location = 0) out vec4 outUV;\n"
943 		"layout(location = 1) out vec4 outColor;\n"
944 		"void main(void)\n"
945 		"{\n"
946 		"	gl_Position = inPosition;\n"
947 		"	outUV = inUV;\n"
948 		"	outColor = inColor;\n"
949 		"}\n"
950 	);
951 
952 #if DRY_RUN_WITHOUT_FDM_EXTENSION
953 	sourceCollections.glslSources.add("frag_produce_subsampled") << glu::FragmentSource(
954 		"#version 450\n"
955 		"#extension GL_EXT_multiview : enable\n"
956 		"layout(location = 0) in vec4 inUV;\n"
957 		"layout(location = 1) in vec4 inColor;\n"
958 		"layout(location = 0) out vec4 fragColor;\n"
959 		"void main(void)\n"
960 		"{\n"
961 		"	fragColor = vec4(inColor.x, inColor.y, 0.5, 0.5);\n"
962 		"}\n"
963 	);
964 
965 	sourceCollections.glslSources.add("frag_update_subsampled") << glu::FragmentSource(
966 		"#version 450\n"
967 		"#extension GL_EXT_multiview : enable\n"
968 		"layout(location = 0) in vec4 inUV;\n"
969 		"layout(location = 1) in vec4 inColor;\n"
970 		"layout(location = 0) out vec4 fragColor;\n"
971 		"void main(void)\n"
972 		"{\n"
973 		"	if (gl_FragCoord.y < 0.5)\n"
974 		"		discard;\n"
975 		"	fragColor = vec4(inColor.x, inColor.y, 0.5, 0.5);\n"
976 		"}\n"
977 	);
978 #else
979 	sourceCollections.glslSources.add("frag_produce_subsampled") << glu::FragmentSource(
980 		"#version 450\n"
981 		"#extension GL_EXT_fragment_invocation_density : enable\n"
982 		"#extension GL_EXT_multiview : enable\n"
983 		"layout(location = 0) in vec4 inUV;\n"
984 		"layout(location = 1) in vec4 inColor;\n"
985 		"layout(location = 0) out vec4 fragColor;\n"
986 		"void main(void)\n"
987 		"{\n"
988 		"	fragColor = vec4(inColor.x, inColor.y, 1.0/float(gl_FragSizeEXT.x), 1.0/(gl_FragSizeEXT.y));\n"
989 		"}\n"
990 	);
991 
992 	sourceCollections.glslSources.add("frag_update_subsampled") << glu::FragmentSource(
993 		"#version 450\n"
994 		"#extension GL_EXT_fragment_invocation_density : enable\n"
995 		"#extension GL_EXT_multiview : enable\n"
996 		"layout(location = 0) in vec4 inUV;\n"
997 		"layout(location = 1) in vec4 inColor;\n"
998 		"layout(location = 0) out vec4 fragColor;\n"
999 		"void main(void)\n"
1000 		"{\n"
1001 		"	if (gl_FragCoord.y < 0.5)\n"
1002 		"		discard;\n"
1003 		"	fragColor = vec4(inColor.x, inColor.y, 1.0/float(gl_FragSizeEXT.x), 1.0/(gl_FragSizeEXT.y));\n"
1004 		"}\n"
1005 	);
1006 #endif
1007 	sourceCollections.glslSources.add("frag_copy_subsampled") << glu::FragmentSource(
1008 		"#version 450\n"
1009 		"#extension GL_EXT_fragment_invocation_density : enable\n"
1010 		"#extension GL_EXT_multiview : enable\n"
1011 		"layout(location = 0) in vec4 inUV;\n"
1012 		"layout(location = 1) in vec4 inColor;\n"
1013 		"layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputAtt;\n"
1014 		"layout(location = 0) out vec4 fragColor;\n"
1015 		"void main(void)\n"
1016 		"{\n"
1017 		"	fragColor = subpassLoad(inputAtt);\n"
1018 		"}\n"
1019 	);
1020 
1021 	sourceCollections.glslSources.add("frag_copy_subsampled_ms") << glu::FragmentSource(
1022 		"#version 450\n"
1023 		"#extension GL_EXT_fragment_invocation_density : enable\n"
1024 		"#extension GL_EXT_multiview : enable\n"
1025 		"layout(location = 0) in vec4 inUV;\n"
1026 		"layout(location = 1) in vec4 inColor;\n"
1027 		"layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInputMS inputAtt;\n"
1028 		"layout(location = 0) out vec4 fragColor;\n"
1029 		"void main(void)\n"
1030 		"{\n"
1031 		"	fragColor = subpassLoad(inputAtt, gl_SampleID);\n"
1032 		"}\n"
1033 	);
1034 
1035 	const char* samplersDefTemplate =
1036 		"layout(binding = ${BINDING})  uniform ${SAMPLER} subsampledImage${BINDING};\n";
1037 	const char* sumColorsTemplate =
1038 		"	fragColor += texture(subsampledImage${BINDING}, inUV.${COMPONENTS});\n";
1039 
1040 	const char* densitymapOutputTemplate =
1041 		"#version 450\n"
1042 		"layout(location = 0) in vec4 inUV;\n"
1043 		"layout(location = 1) in vec4 inColor;\n"
1044 		"${SAMPLERS_DEF}"
1045 		"layout(location = 0) out vec4 fragColor;\n"
1046 		"void main(void)\n"
1047 		"{\n"
1048 		"	fragColor = vec4(0);\n"
1049 		"${SUM_COLORS}"
1050 		"	fragColor /= float(${COUNT});\n"
1051 		"}\n";
1052 
1053 	std::map<std::string, std::string> parameters
1054 	{
1055 		{ "SAMPLER",		"" },
1056 		{ "BINDING",		"" },
1057 		{ "COMPONENTS",		"" },
1058 		{ "COUNT",			std::to_string(m_testParams.samplersCount) },
1059 		{ "SAMPLERS_DEF",	"" },
1060 		{ "SUM_COLORS",		"" },
1061 	};
1062 
1063 	std::string sampler2dDefs;
1064 	std::string sampler2dSumColors;
1065 	std::string sampler2dArrayDefs;
1066 	std::string sampler2dArraySumColors;
1067 	for (deUint32 samplerIndex = 0; samplerIndex < m_testParams.samplersCount; ++samplerIndex)
1068 	{
1069 		parameters["BINDING"]		 = std::to_string(samplerIndex);
1070 
1071 		parameters["COMPONENTS"]	 = "xy";
1072 		parameters["SAMPLER"]		 = "sampler2D";
1073 		sampler2dDefs				+= tcu::StringTemplate(samplersDefTemplate).specialize(parameters);
1074 		sampler2dSumColors			+= tcu::StringTemplate(sumColorsTemplate).specialize(parameters);
1075 
1076 		parameters["COMPONENTS"]	 = "xyz";
1077 		parameters["SAMPLER"]		 = "sampler2DArray";
1078 		sampler2dArrayDefs			+= tcu::StringTemplate(samplersDefTemplate).specialize(parameters);
1079 		sampler2dArraySumColors		+= tcu::StringTemplate(sumColorsTemplate).specialize(parameters);
1080 	}
1081 
1082 	parameters["SAMPLERS_DEF"]	= sampler2dDefs;
1083 	parameters["SUM_COLORS"]	= sampler2dSumColors;
1084 	sourceCollections.glslSources.add("frag_output_2d")
1085 		<< glu::FragmentSource(tcu::StringTemplate(densitymapOutputTemplate).specialize(parameters));
1086 
1087 	parameters["SAMPLERS_DEF"]	= sampler2dArrayDefs;
1088 	parameters["SUM_COLORS"]	= sampler2dArraySumColors;
1089 	sourceCollections.glslSources.add("frag_output_2darray")
1090 		<< glu::FragmentSource(tcu::StringTemplate(densitymapOutputTemplate).specialize(parameters));
1091 }
1092 
createInstance(Context & context) const1093 TestInstance* FragmentDensityMapTest::createInstance(Context& context) const
1094 {
1095 	return new FragmentDensityMapTestInstance(context, m_testParams);
1096 }
1097 
checkSupport(Context & context) const1098 void FragmentDensityMapTest::checkSupport(Context& context) const
1099 {
1100 	const InstanceInterface&	vki					= context.getInstanceInterface();
1101 	const VkPhysicalDevice		vkPhysicalDevice	= context.getPhysicalDevice();
1102 
1103 #if DRY_RUN_WITHOUT_FDM_EXTENSION
1104 	if (m_testParams.viewCount > 1)
1105 	{
1106 		context.requireDeviceFunctionality("VK_KHR_multiview");
1107 		if (!context.getMultiviewFeatures().multiview)
1108 			TCU_THROW(NotSupportedError, "Implementation does not support multiview feature");
1109 	}
1110 #else
1111 	context.requireDeviceFunctionality("VK_EXT_fragment_density_map");
1112 
1113 
1114 
1115 	VkPhysicalDeviceFragmentDensityMapFeaturesEXT		fragmentDensityMapFeatures		= initVulkanStructure();
1116 	VkPhysicalDeviceFragmentDensityMap2FeaturesEXT		fragmentDensityMap2Features		= initVulkanStructure(&fragmentDensityMapFeatures);
1117 	VkPhysicalDeviceFeatures2KHR						features2						= initVulkanStructure(&fragmentDensityMap2Features);
1118 
1119 	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
1120 
1121 	const auto& fragmentDensityMap2Properties	= context.getFragmentDensityMap2PropertiesEXT();
1122 
1123 	if (!fragmentDensityMapFeatures.fragmentDensityMap)
1124 		TCU_THROW(NotSupportedError, "fragmentDensityMap feature is not supported");
1125 	if (m_testParams.dynamicDensityMap && !fragmentDensityMapFeatures.fragmentDensityMapDynamic)
1126 		TCU_THROW(NotSupportedError, "fragmentDensityMapDynamic feature is not supported");
1127 	if (m_testParams.nonSubsampledImages && !fragmentDensityMapFeatures.fragmentDensityMapNonSubsampledImages)
1128 		TCU_THROW(NotSupportedError, "fragmentDensityMapNonSubsampledImages feature is not supported");
1129 
1130 	if (m_testParams.deferredDensityMap)
1131 	{
1132 		context.requireDeviceFunctionality("VK_EXT_fragment_density_map2");
1133 		if (!fragmentDensityMap2Features.fragmentDensityMapDeferred)
1134 			TCU_THROW(NotSupportedError, "fragmentDensityMapDeferred feature is not supported");
1135 	}
1136 	if (m_testParams.subsampledLoads)
1137 	{
1138 		context.requireDeviceFunctionality("VK_EXT_fragment_density_map2");
1139 		if (!fragmentDensityMap2Properties.subsampledLoads)
1140 			TCU_THROW(NotSupportedError, "subsampledLoads property is not supported");
1141 	}
1142 	if (m_testParams.coarseReconstruction)
1143 	{
1144 		context.requireDeviceFunctionality("VK_EXT_fragment_density_map2");
1145 		if (!fragmentDensityMap2Properties.subsampledCoarseReconstructionEarlyAccess)
1146 			TCU_THROW(NotSupportedError, "subsampledCoarseReconstructionEarlyAccess property is not supported");
1147 	}
1148 
1149 	if (m_testParams.viewCount > 1)
1150 	{
1151 		context.requireDeviceFunctionality("VK_KHR_multiview");
1152 		if (!context.getMultiviewFeatures().multiview)
1153 			TCU_THROW(NotSupportedError, "Implementation does not support multiview feature");
1154 
1155 		if (m_testParams.viewCount > 2)
1156 		{
1157 			context.requireDeviceFunctionality("VK_EXT_fragment_density_map2");
1158 			if (m_testParams.viewCount > fragmentDensityMap2Properties.maxSubsampledArrayLayers)
1159 				TCU_THROW(NotSupportedError, "Maximum number of VkImageView array layers for usages supporting subsampled samplers is to small");
1160 		}
1161 	}
1162 
1163 	if (!m_testParams.nonSubsampledImages && (m_testParams.samplersCount > 1))
1164 	{
1165 		context.requireDeviceFunctionality("VK_EXT_fragment_density_map2");
1166 		if (m_testParams.samplersCount > fragmentDensityMap2Properties.maxDescriptorSetSubsampledSamplers)
1167 			TCU_THROW(NotSupportedError, "Required number of subsampled samplers is not supported");
1168 	}
1169 #endif
1170 
1171 	vk::VkImageUsageFlags	colorImageUsage			= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1172 	if (m_testParams.makeCopy)
1173 		colorImageUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1174 
1175 	deUint32				colorImageCreateFlags	= m_testParams.nonSubsampledImages ? 0u : (deUint32)VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT;
1176 	VkImageFormatProperties	imageFormatProperties	(getPhysicalDeviceImageFormatProperties(vki, vkPhysicalDevice, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, colorImageUsage, colorImageCreateFlags));
1177 
1178 	if ((imageFormatProperties.sampleCounts & m_testParams.colorSamples) == 0)
1179 		TCU_THROW(NotSupportedError, "Color image type not supported");
1180 
1181 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
1182 		!context.getPortabilitySubsetFeatures().multisampleArrayImage &&
1183 		(m_testParams.colorSamples != VK_SAMPLE_COUNT_1_BIT) && (m_testParams.viewCount != 1))
1184 	{
1185 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
1186 	}
1187 }
1188 
FragmentDensityMapTestInstance(Context & context,const TestParams & testParams)1189 FragmentDensityMapTestInstance::FragmentDensityMapTestInstance(Context&				context,
1190 															   const TestParams&	testParams)
1191 	: vkt::TestInstance	(context)
1192 	, m_testParams		(testParams)
1193 {
1194 	m_renderSize		= tcu::UVec2(deFloorFloatToInt32(m_testParams.renderMultiplier * static_cast<float>(m_testParams.densityMapSize.x())),
1195 									 deFloorFloatToInt32(m_testParams.renderMultiplier * static_cast<float>(m_testParams.densityMapSize.y())));
1196 	m_densityValue		= tcu::Vec2(1.0f / static_cast<float>(m_testParams.fragmentArea.x()),
1197 									1.0f / static_cast<float>(m_testParams.fragmentArea.y()));
1198 	m_viewMask			= (m_testParams.viewCount > 1) ? ((1u << m_testParams.viewCount) - 1u) : 0u;
1199 
1200 	const DeviceInterface&		vk							= m_context.getDeviceInterface();
1201 	const VkDevice				vkDevice					= getDevice(m_context);
1202 	const VkPhysicalDevice		vkPhysicalDevice			= m_context.getPhysicalDevice();
1203 	const deUint32				queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1204 	const VkQueue				queue						= getDeviceQueue(vk, vkDevice, queueFamilyIndex, 0);
1205 	SimpleAllocator				memAlloc					(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), vkPhysicalDevice));
1206 	const VkComponentMapping	componentMappingRGBA		= makeComponentMappingRGBA();
1207 
1208 	// calculate all image sizes, image usage flags, view types etc.
1209 	deUint32					densitiMapCount				= 1 + m_testParams.subsampledLoads;
1210 	VkExtent3D					densityMapImageSize			{ m_testParams.densityMapSize.x(), m_testParams.densityMapSize.y(), 1 };
1211 	deUint32					densityMapImageLayers		= m_testParams.viewCount;
1212 	VkImageViewType				densityMapImageViewType		= (m_testParams.viewCount > 1) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
1213 	vk::VkImageUsageFlags		densityMapImageUsage		= VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1214 	deUint32					densityMapImageViewFlags	= 0u;
1215 
1216 	VkExtent3D					colorImageSize				{ m_renderSize.x() / m_testParams.viewCount, m_renderSize.y(), 1 };
1217 	deUint32					colorImageLayers			= densityMapImageLayers;
1218 	VkImageViewType				colorImageViewType			= densityMapImageViewType;
1219 	vk::VkImageUsageFlags		colorImageUsage				= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1220 	deUint32					colorImageCreateFlags		= m_testParams.nonSubsampledImages ? 0u : (deUint32)VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT;
1221 	bool						isColorImageMultisampled	= m_testParams.colorSamples != VK_SAMPLE_COUNT_1_BIT;
1222 
1223 	VkExtent3D					outputImageSize				{ m_renderSize.x(), m_renderSize.y(), 1 };
1224 
1225 	if (m_testParams.dynamicDensityMap)
1226 	{
1227 		DE_ASSERT(!m_testParams.subsampledLoads);
1228 
1229 		densityMapImageUsage		= VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1230 		densityMapImageViewFlags	= (deUint32)VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT;
1231 	}
1232 	else if (m_testParams.deferredDensityMap)
1233 		densityMapImageViewFlags	= (deUint32)VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT;
1234 	if (m_testParams.makeCopy)
1235 		colorImageUsage				|= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1236 
1237 #if DRY_RUN_WITHOUT_FDM_EXTENSION
1238 	colorImageCreateFlags		= 0u;
1239 	densityMapImageUsage		= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1240 	densityMapImageViewFlags	= 0u;
1241 #endif
1242 
1243 	// Create subsampled color image
1244 	prepareImageAndImageView(vk, vkDevice, memAlloc, colorImageCreateFlags, VK_FORMAT_R8G8B8A8_UNORM,
1245 		colorImageSize, colorImageLayers, m_testParams.colorSamples,
1246 		colorImageUsage, queueFamilyIndex, 0u, colorImageViewType,
1247 		componentMappingRGBA, { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, colorImageLayers },
1248 		m_colorImage, m_colorImageAlloc, m_colorImageView);
1249 
1250 	// Create subsampled color image for resolve operation ( when multisampling is used )
1251 	if (isColorImageMultisampled)
1252 	{
1253 		prepareImageAndImageView(vk, vkDevice, memAlloc, colorImageCreateFlags, VK_FORMAT_R8G8B8A8_UNORM,
1254 			colorImageSize, colorImageLayers, VK_SAMPLE_COUNT_1_BIT,
1255 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, queueFamilyIndex, 0u, colorImageViewType,
1256 			componentMappingRGBA, { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, colorImageLayers },
1257 			m_colorResolvedImage, m_colorResolvedImageAlloc, m_colorResolvedImageView);
1258 	}
1259 
1260 	// Create subsampled image copy
1261 	if (m_testParams.makeCopy)
1262 	{
1263 		prepareImageAndImageView(vk, vkDevice, memAlloc, colorImageCreateFlags, VK_FORMAT_R8G8B8A8_UNORM,
1264 			colorImageSize, colorImageLayers, m_testParams.colorSamples,
1265 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, queueFamilyIndex, 0u, colorImageViewType,
1266 			componentMappingRGBA, { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, colorImageLayers },
1267 			m_colorCopyImage, m_colorCopyImageAlloc, m_colorCopyImageView);
1268 	}
1269 
1270 	// Create output image ( data from subsampled color image will be copied into it using sampler with VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT )
1271 	prepareImageAndImageView(vk, vkDevice, memAlloc, 0u, VK_FORMAT_R8G8B8A8_UNORM,
1272 		outputImageSize, 1u, VK_SAMPLE_COUNT_1_BIT,
1273 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, queueFamilyIndex, 0u, VK_IMAGE_VIEW_TYPE_2D,
1274 		componentMappingRGBA, { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },
1275 		m_outputImage, m_outputImageAlloc, m_outputImageView);
1276 
1277 	// Create density map image/images
1278 	for (deUint32 mapIndex = 0; mapIndex < densitiMapCount; ++mapIndex)
1279 	{
1280 		Move<VkImage>			densityMapImage;
1281 		de::MovePtr<Allocation>	densityMapImageAlloc;
1282 		Move<VkImageView>		densityMapImageView;
1283 
1284 		prepareImageAndImageView(vk, vkDevice, memAlloc, 0u, m_testParams.densityMapFormat,
1285 			densityMapImageSize, densityMapImageLayers, VK_SAMPLE_COUNT_1_BIT,
1286 			densityMapImageUsage, queueFamilyIndex, densityMapImageViewFlags, densityMapImageViewType,
1287 			componentMappingRGBA, { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, densityMapImageLayers },
1288 			densityMapImage, densityMapImageAlloc, densityMapImageView);
1289 
1290 		m_densityMapImages.push_back(VkImageSp(new Unique<VkImage>(densityMapImage)));
1291 		m_densityMapImageAllocs.push_back(AllocationSp(densityMapImageAlloc.release()));
1292 		m_densityMapImageViews.push_back(VkImageViewSp(new Unique<VkImageView>(densityMapImageView)));
1293 	}
1294 
1295 	// Create and fill staging buffer, copy its data to density map image
1296 	if (!m_testParams.dynamicDensityMap)
1297 	{
1298 		tcu::TextureFormat				densityMapTextureFormat = vk::mapVkFormat(m_testParams.densityMapFormat);
1299 		VkDeviceSize					stagingBufferSize		= tcu::getPixelSize(densityMapTextureFormat) * densityMapImageSize.width * densityMapImageSize.height * densityMapImageLayers;
1300 		const vk::VkBufferCreateInfo	stagingBufferCreateInfo =
1301 		{
1302 			vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1303 			DE_NULL,
1304 			0u,									// flags
1305 			stagingBufferSize,					// size
1306 			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,	// usage
1307 			vk::VK_SHARING_MODE_EXCLUSIVE,		// sharingMode
1308 			0u,									// queueFamilyCount
1309 			DE_NULL,							// pQueueFamilyIndices
1310 		};
1311 		vk::Move<vk::VkBuffer>			stagingBuffer		= vk::createBuffer(vk, vkDevice, &stagingBufferCreateInfo);
1312 		const vk::VkMemoryRequirements	stagingRequirements = vk::getBufferMemoryRequirements(vk, vkDevice, *stagingBuffer);
1313 		de::MovePtr<vk::Allocation>		stagingAllocation	= memAlloc.allocate(stagingRequirements, MemoryRequirement::HostVisible);
1314 		VK_CHECK(vk.bindBufferMemory(vkDevice, *stagingBuffer, stagingAllocation->getMemory(), stagingAllocation->getOffset()));
1315 		tcu::PixelBufferAccess			stagingBufferAccess	(densityMapTextureFormat, densityMapImageSize.width, densityMapImageSize.height, densityMapImageLayers, stagingAllocation->getHostPtr());
1316 		tcu::Vec4						fragmentArea		(m_densityValue.x(), m_densityValue.y(), 0.0f, 1.0f);
1317 
1318 		for (deUint32 mapIndex = 0; mapIndex < densitiMapCount; ++mapIndex)
1319 		{
1320 			// Fill staging buffer with one color
1321 			tcu::clear(stagingBufferAccess, fragmentArea);
1322 			flushAlloc(vk, vkDevice, *stagingAllocation);
1323 
1324 			copyBufferToImage
1325 			(
1326 				vk, vkDevice, queue, queueFamilyIndex,
1327 				*stagingBuffer, stagingBufferSize,
1328 				densityMapImageSize, densityMapImageLayers, **m_densityMapImages[mapIndex]
1329 			);
1330 
1331 			std::swap(fragmentArea.m_data[0], fragmentArea.m_data[1]);
1332 		}
1333 	}
1334 
1335 	deUint32 samplerCreateFlags = (deUint32)VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT;
1336 	if (m_testParams.coarseReconstruction)
1337 		samplerCreateFlags		|= (deUint32)VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT;
1338 	if (m_testParams.nonSubsampledImages)
1339 		samplerCreateFlags		= 0u;
1340 
1341 #if DRY_RUN_WITHOUT_FDM_EXTENSION
1342 	samplerCreateFlags = 0u;
1343 #endif
1344 
1345 	const struct VkSamplerCreateInfo samplerInfo
1346 	{
1347 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// sType
1348 		DE_NULL,										// pNext
1349 		(VkSamplerCreateFlags)samplerCreateFlags,		// flags
1350 		VK_FILTER_NEAREST,								// magFilter
1351 		VK_FILTER_NEAREST,								// minFilter
1352 		VK_SAMPLER_MIPMAP_MODE_NEAREST,					// mipmapMode
1353 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// addressModeU
1354 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// addressModeV
1355 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// addressModeW
1356 		0.0f,											// mipLodBias
1357 		VK_FALSE,										// anisotropyEnable
1358 		1.0f,											// maxAnisotropy
1359 		DE_FALSE,										// compareEnable
1360 		VK_COMPARE_OP_ALWAYS,							// compareOp
1361 		0.0f,											// minLod
1362 		0.0f,											// maxLod
1363 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,		// borderColor
1364 		VK_FALSE,										// unnormalizedCoords
1365 	};
1366 
1367 	// Create a sampler that are able to read from subsampled image
1368 	// (more than one sampler is needed only for 4 maxDescriptorSetSubsampledSamplers tests)
1369 	for (deUint32 samplerIndex = 0; samplerIndex < testParams.samplersCount; ++samplerIndex)
1370 		m_colorSamplers.push_back(VkSamplerSp(new Unique<VkSampler>(createSampler(vk, vkDevice, &samplerInfo))));
1371 
1372 	// Create render passes
1373 	if (testParams.dynamicDensityMap)
1374 		m_renderPassProduceDynamicDensityMap	= createRenderPassProduceDynamicDensityMap(vk, vkDevice, m_viewMask, testParams);
1375 	m_renderPassProduceSubsampledImage			= createRenderPassProduceSubsampledImage(vk, vkDevice, m_viewMask, testParams.makeCopy, false, testParams);
1376 	if (testParams.subsampledLoads)
1377 		m_renderPassUpdateSubsampledImage		= createRenderPassProduceSubsampledImage(vk, vkDevice, m_viewMask, false, true, testParams);
1378 	m_renderPassOutputSubsampledImage			= createRenderPassOutputSubsampledImage(vk, vkDevice);
1379 
1380 	std::vector<VkImageView> imageViewsProduceSubsampledImage = { *m_colorImageView };
1381 	if (isColorImageMultisampled)
1382 		imageViewsProduceSubsampledImage.push_back(*m_colorResolvedImageView);
1383 	if (testParams.makeCopy)
1384 		imageViewsProduceSubsampledImage.push_back(*m_colorCopyImageView);
1385 	imageViewsProduceSubsampledImage.push_back(**m_densityMapImageViews[0]);
1386 
1387 	std::vector<VkImageView> imageViewsUpdateSubsampledImage = { *m_colorImageView };
1388 	if (testParams.subsampledLoads)
1389 		imageViewsUpdateSubsampledImage.push_back(**m_densityMapImageViews[1]);
1390 
1391 #if DRY_RUN_WITHOUT_FDM_EXTENSION
1392 	imageViewsProduceSubsampledImage.pop_back();
1393 	imageViewsUpdateSubsampledImage.pop_back();
1394 #endif
1395 
1396 	// Create framebuffers
1397 	if (testParams.dynamicDensityMap)
1398 	{
1399 		m_framebufferProduceDynamicDensityMap = createFrameBuffer(vk, vkDevice,
1400 			*m_renderPassProduceDynamicDensityMap,
1401 			densityMapImageSize,
1402 			{ **m_densityMapImageViews[0] });
1403 	}
1404 	m_framebufferProduceSubsampledImage = createFrameBuffer(vk, vkDevice,
1405 		*m_renderPassProduceSubsampledImage,
1406 		colorImageSize,
1407 		imageViewsProduceSubsampledImage);
1408 	if (testParams.subsampledLoads)
1409 	{
1410 		m_framebufferUpdateSubsampledImage = createFrameBuffer(vk, vkDevice,
1411 			*m_renderPassUpdateSubsampledImage,
1412 			colorImageSize,
1413 			imageViewsUpdateSubsampledImage);
1414 	}
1415 	m_framebufferOutputSubsampledImage = createFrameBuffer(vk, vkDevice,
1416 		*m_renderPassOutputSubsampledImage,
1417 		outputImageSize,
1418 		{ *m_outputImageView });
1419 
1420 	// Create pipeline layout for subpasses that do not use any descriptors
1421 	{
1422 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1423 		{
1424 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
1425 			DE_NULL,										// const void*					pNext;
1426 			0u,												// VkPipelineLayoutCreateFlags	flags;
1427 			0u,												// deUint32						setLayoutCount;
1428 			DE_NULL,										// const VkDescriptorSetLayout*	pSetLayouts;
1429 			0u,												// deUint32						pushConstantRangeCount;
1430 			DE_NULL											// const VkPushConstantRange*	pPushConstantRanges;
1431 		};
1432 
1433 		m_pipelineLayoutNoDescriptors = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1434 	}
1435 
1436 	// Create pipeline layout for subpass that copies data or resamples subsampled image
1437 	if (m_testParams.makeCopy || m_testParams.subsampledLoads)
1438 	{
1439 		m_descriptorSetLayoutOperateOnSubsampledImage =
1440 			DescriptorSetLayoutBuilder()
1441 			.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL)
1442 			.build(vk, vkDevice);
1443 
1444 		// Create and bind descriptor set
1445 		m_descriptorPoolOperateOnSubsampledImage =
1446 			DescriptorPoolBuilder()
1447 			.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
1448 			.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1449 
1450 		m_pipelineLayoutOperateOnSubsampledImage	= makePipelineLayout(vk, vkDevice, *m_descriptorSetLayoutOperateOnSubsampledImage);
1451 		m_descriptorSetOperateOnSubsampledImage		= makeDescriptorSet(vk, vkDevice, *m_descriptorPoolOperateOnSubsampledImage, *m_descriptorSetLayoutOperateOnSubsampledImage);
1452 
1453 		const VkDescriptorImageInfo inputImageInfo =
1454 		{
1455 			DE_NULL,											// VkSampleri		sampler;
1456 			*m_colorImageView,									// VkImageView		imageView;
1457 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL			// VkImageLayout	imageLayout;
1458 		};
1459 		DescriptorSetUpdateBuilder()
1460 			.writeSingle(*m_descriptorSetOperateOnSubsampledImage, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &inputImageInfo)
1461 			.update(vk, vkDevice);
1462 	}
1463 
1464 	// Create pipeline layout for last render pass (output subsampled image)
1465 	{
1466 		DescriptorSetLayoutBuilder	descriptorSetLayoutBuilder;
1467 		DescriptorPoolBuilder		descriptorPoolBuilder;
1468 		for (deUint32 samplerIndex = 0; samplerIndex < testParams.samplersCount; ++samplerIndex)
1469 		{
1470 			descriptorSetLayoutBuilder.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &(*m_colorSamplers[samplerIndex]).get());
1471 			descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, samplerIndex + 1u);
1472 		}
1473 
1474 		m_descriptorSetLayoutOutputSubsampledImage	= descriptorSetLayoutBuilder.build(vk, vkDevice);
1475 		m_descriptorPoolOutputSubsampledImage		= descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1476 		m_pipelineLayoutOutputSubsampledImage		= makePipelineLayout(vk, vkDevice, *m_descriptorSetLayoutOutputSubsampledImage);
1477 		m_descriptorSetOutputSubsampledImage		= makeDescriptorSet(vk, vkDevice, *m_descriptorPoolOutputSubsampledImage, *m_descriptorSetLayoutOutputSubsampledImage);
1478 
1479 		VkImageView srcImageView = *m_colorImageView;
1480 		if (isColorImageMultisampled)
1481 			srcImageView = *m_colorResolvedImageView;
1482 		else if (m_testParams.makeCopy)
1483 			srcImageView = *m_colorCopyImageView;
1484 
1485 		const VkDescriptorImageInfo inputImageInfo =
1486 		{
1487 			DE_NULL,									// VkSampleri		sampler;
1488 			srcImageView,								// VkImageView		imageView;
1489 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
1490 		};
1491 
1492 		DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
1493 		for (deUint32 samplerIndex = 0; samplerIndex < testParams.samplersCount; ++samplerIndex)
1494 			descriptorSetUpdateBuilder.writeSingle(*m_descriptorSetOutputSubsampledImage, DescriptorSetUpdateBuilder::Location::binding(samplerIndex), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &inputImageInfo);
1495 		descriptorSetUpdateBuilder.update(vk, vkDevice);
1496 	}
1497 
1498 	// Load vertex and fragment shaders
1499 	auto& bc = m_context.getBinaryCollection();
1500 	m_vertexCommonShaderModule						= createShaderModule(vk, vkDevice, bc.get("vert"), 0);
1501 	m_fragmentShaderModuleProduceSubsampledImage	= createShaderModule(vk, vkDevice, bc.get("frag_produce_subsampled"), 0);
1502 	if (m_testParams.makeCopy)
1503 	{
1504 		const char* moduleName = isColorImageMultisampled ? "frag_copy_subsampled_ms" : "frag_copy_subsampled";
1505 		m_fragmentShaderModuleCopySubsampledImage = createShaderModule(vk, vkDevice, bc.get(moduleName), 0);
1506 	}
1507 	if (m_testParams.subsampledLoads)
1508 	{
1509 		const char* moduleName = "frag_update_subsampled";
1510 		m_fragmentShaderModuleUpdateSubsampledImage = createShaderModule(vk, vkDevice, bc.get(moduleName), 0);
1511 	}
1512 	const char* moduleName = (m_testParams.viewCount > 1) ? "frag_output_2darray" : "frag_output_2d";
1513 	m_fragmentShaderModuleOutputSubsampledImage = createShaderModule(vk, vkDevice, bc.get(moduleName), 0);
1514 
1515 	// Create pipelines
1516 	{
1517 		const VkVertexInputBindingDescription vertexInputBindingDescription =
1518 		{
1519 			0u,																// deUint32					binding;
1520 			sizeof(Vertex4RGBA),											// deUint32					strideInBytes;
1521 			VK_VERTEX_INPUT_RATE_VERTEX										// VkVertexInputStepRate	inputRate;
1522 		};
1523 
1524 		std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions =
1525 		{
1526 			{ 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
1527 			{ 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(sizeof(float) * 4) },
1528 			{ 2u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(sizeof(float) * 8) }
1529 		};
1530 
1531 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1532 		{
1533 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1534 			DE_NULL,														// const void*								pNext;
1535 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
1536 			1u,																// deUint32									vertexBindingDescriptionCount;
1537 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1538 			static_cast<deUint32>(vertexInputAttributeDescriptions.size()),	// deUint32									vertexAttributeDescriptionCount;
1539 			vertexInputAttributeDescriptions.data()							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1540 		};
1541 
1542 		const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
1543 		{
1544 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
1545 			DE_NULL,													// const void*								pNext
1546 			(VkPipelineMultisampleStateCreateFlags)0u,					// VkPipelineMultisampleStateCreateFlags	flags
1547 			(VkSampleCountFlagBits)m_testParams.colorSamples,			// VkSampleCountFlagBits					rasterizationSamples
1548 			VK_FALSE,													// VkBool32									sampleShadingEnable
1549 			1.0f,														// float									minSampleShading
1550 			DE_NULL,													// const VkSampleMask*						pSampleMask
1551 			VK_FALSE,													// VkBool32									alphaToCoverageEnable
1552 			VK_FALSE													// VkBool32									alphaToOneEnable
1553 		};
1554 
1555 		const std::vector<VkViewport>	viewportsProduceDynamicDensityMap	{ makeViewport(densityMapImageSize.width, densityMapImageSize.height) };
1556 		const std::vector<VkRect2D>		scissorsProduceDynamicDensityMap	{ makeRect2D(densityMapImageSize.width, densityMapImageSize.height) };
1557 		const std::vector<VkViewport>	viewportsSubsampledImage			{ makeViewport(colorImageSize.width, colorImageSize.height) };
1558 		const std::vector<VkRect2D>		scissorsSubsampledImage				{ makeRect2D(colorImageSize.width, colorImageSize.height) };
1559 		const std::vector<VkViewport>	viewportsOutputSubsampledImage		{ makeViewport(outputImageSize.width, outputImageSize.height) };
1560 		const std::vector<VkRect2D>		scissorsOutputSubsampledImage		{ makeRect2D(outputImageSize.width, outputImageSize.height) };
1561 
1562 		if (testParams.dynamicDensityMap)
1563 			m_graphicsPipelineProduceDynamicDensityMap = makeGraphicsPipeline(vk,							// const DeviceInterface&							vk
1564 															vkDevice,										// const VkDevice									device
1565 															*m_pipelineLayoutNoDescriptors,					// const VkPipelineLayout							pipelineLayout
1566 															*m_vertexCommonShaderModule,					// const VkShaderModule								vertexShaderModule
1567 															DE_NULL,										// const VkShaderModule								tessellationControlModule
1568 															DE_NULL,										// const VkShaderModule								tessellationEvalModule
1569 															DE_NULL,										// const VkShaderModule								geometryShaderModule
1570 															*m_fragmentShaderModuleProduceSubsampledImage,	// const VkShaderModule								fragmentShaderModule
1571 															*m_renderPassProduceDynamicDensityMap,			// const VkRenderPass								renderPass
1572 															viewportsProduceDynamicDensityMap,				// const std::vector<VkViewport>&					viewports
1573 															scissorsProduceDynamicDensityMap,				// const std::vector<VkRect2D>&						scissors
1574 															VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,			// const VkPrimitiveTopology						topology
1575 															0u,												// const deUint32									subpass
1576 															0u,												// const deUint32									patchControlPoints
1577 															&vertexInputStateParams);						// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
1578 
1579 		m_graphicsPipelineProduceSubsampledImage = makeGraphicsPipeline(vk,									// const DeviceInterface&							vk
1580 															vkDevice,										// const VkDevice									device
1581 															*m_pipelineLayoutNoDescriptors,					// const VkPipelineLayout							pipelineLayout
1582 															*m_vertexCommonShaderModule,					// const VkShaderModule								vertexShaderModule
1583 															DE_NULL,										// const VkShaderModule								tessellationControlModule
1584 															DE_NULL,										// const VkShaderModule								tessellationEvalModule
1585 															DE_NULL,										// const VkShaderModule								geometryShaderModule
1586 															*m_fragmentShaderModuleProduceSubsampledImage,	// const VkShaderModule								fragmentShaderModule
1587 															*m_renderPassProduceSubsampledImage,			// const VkRenderPass								renderPass
1588 															viewportsSubsampledImage,						// const std::vector<VkViewport>&					viewports
1589 															scissorsSubsampledImage,						// const std::vector<VkRect2D>&						scissors
1590 															VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,			// const VkPrimitiveTopology						topology
1591 															0u,												// const deUint32									subpass
1592 															0u,												// const deUint32									patchControlPoints
1593 															&vertexInputStateParams,						// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
1594 															DE_NULL,										// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
1595 															&multisampleStateCreateInfo);					// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
1596 		if(m_testParams.makeCopy)
1597 			m_graphicsPipelineCopySubsampledImage = makeGraphicsPipeline(vk,								// const DeviceInterface&							vk
1598 															vkDevice,										// const VkDevice									device
1599 															*m_pipelineLayoutOperateOnSubsampledImage,		// const VkPipelineLayout							pipelineLayout
1600 															*m_vertexCommonShaderModule,					// const VkShaderModule								vertexShaderModule
1601 															DE_NULL,										// const VkShaderModule								tessellationControlModule
1602 															DE_NULL,										// const VkShaderModule								tessellationEvalModule
1603 															DE_NULL,										// const VkShaderModule								geometryShaderModule
1604 															*m_fragmentShaderModuleCopySubsampledImage,		// const VkShaderModule								fragmentShaderModule
1605 															*m_renderPassProduceSubsampledImage,			// const VkRenderPass								renderPass
1606 															viewportsSubsampledImage,						// const std::vector<VkViewport>&					viewports
1607 															scissorsSubsampledImage,						// const std::vector<VkRect2D>&						scissors
1608 															VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,			// const VkPrimitiveTopology						topology
1609 															1u,												// const deUint32									subpass
1610 															0u,												// const deUint32									patchControlPoints
1611 															&vertexInputStateParams,						// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
1612 															DE_NULL,										// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
1613 															&multisampleStateCreateInfo);					// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
1614 		if (m_testParams.subsampledLoads)
1615 			m_graphicsPipelineUpdateSubsampledImage = makeGraphicsPipeline(vk,								// const DeviceInterface&							vk
1616 															vkDevice,										// const VkDevice									device
1617 															*m_pipelineLayoutOperateOnSubsampledImage,		// const VkPipelineLayout							pipelineLayout
1618 															*m_vertexCommonShaderModule,					// const VkShaderModule								vertexShaderModule
1619 															DE_NULL,										// const VkShaderModule								tessellationControlModule
1620 															DE_NULL,										// const VkShaderModule								tessellationEvalModule
1621 															DE_NULL,										// const VkShaderModule								geometryShaderModule
1622 															*m_fragmentShaderModuleUpdateSubsampledImage,	// const VkShaderModule								fragmentShaderModule
1623 															*m_renderPassUpdateSubsampledImage,				// const VkRenderPass								renderPass
1624 															viewportsSubsampledImage,						// const std::vector<VkViewport>&					viewports
1625 															scissorsSubsampledImage,						// const std::vector<VkRect2D>&						scissors
1626 															VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,			// const VkPrimitiveTopology						topology
1627 															0u,												// const deUint32									subpass
1628 															0u,												// const deUint32									patchControlPoints
1629 															&vertexInputStateParams,						// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
1630 															DE_NULL,										// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
1631 															&multisampleStateCreateInfo);					// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
1632 
1633 		m_graphicsPipelineOutputSubsampledImage = makeGraphicsPipeline(vk,									// const DeviceInterface&							vk
1634 															vkDevice,										// const VkDevice									device
1635 															*m_pipelineLayoutOutputSubsampledImage,			// const VkPipelineLayout							pipelineLayout
1636 															*m_vertexCommonShaderModule,					// const VkShaderModule								vertexShaderModule
1637 															DE_NULL,										// const VkShaderModule								tessellationControlModule
1638 															DE_NULL,										// const VkShaderModule								tessellationEvalModule
1639 															DE_NULL,										// const VkShaderModule								geometryShaderModule
1640 															*m_fragmentShaderModuleOutputSubsampledImage,	// const VkShaderModule								fragmentShaderModule
1641 															*m_renderPassOutputSubsampledImage,				// const VkRenderPass								renderPass
1642 															viewportsOutputSubsampledImage,					// const std::vector<VkViewport>&					viewports
1643 															scissorsOutputSubsampledImage,					// const std::vector<VkRect2D>&						scissors
1644 															VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,			// const VkPrimitiveTopology						topology
1645 															0u,												// const deUint32									subpass
1646 															0u,												// const deUint32									patchControlPoints
1647 															&vertexInputStateParams);						// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
1648 	}
1649 
1650 	// Create vertex buffers
1651 	const tcu::Vec2 densityX(m_densityValue.x());
1652 	const tcu::Vec2 densityY(m_densityValue.y());
1653 	m_vertices			= createFullscreenMesh(1, {0.0f, 1.0f}, {0.0f, 1.0f});							// create fullscreen quad with gradient
1654 	if (testParams.dynamicDensityMap)
1655 		m_verticesDDM	= createFullscreenMesh(1, densityX, densityY);									// create fullscreen quad with single color
1656 	m_verticesOutput	= createFullscreenMesh(m_testParams.viewCount, { 0.0f, 0.0f }, { 0.0f, 0.0f });	// create fullscreen mesh with black color
1657 
1658 	createVertexBuffer(vk, vkDevice, queueFamilyIndex, memAlloc, m_vertices, m_vertexBuffer, m_vertexBufferAlloc);
1659 	if (testParams.dynamicDensityMap)
1660 		createVertexBuffer(vk, vkDevice, queueFamilyIndex, memAlloc, m_verticesDDM, m_vertexBufferDDM, m_vertexBufferAllocDDM);
1661 	createVertexBuffer(vk, vkDevice, queueFamilyIndex, memAlloc, m_verticesOutput, m_vertexBufferOutput, m_vertexBufferOutputAlloc);
1662 
1663 	// Create command pool and command buffer
1664 	m_cmdPool	= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1665 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1666 
1667 	typedef RenderpassSubpass2 RPS2;
1668 	const typename RPS2::SubpassBeginInfo	subpassBeginInfo		(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1669 	const typename RPS2::SubpassEndInfo		subpassEndInfo			(DE_NULL);
1670 	const VkDeviceSize						vertexBufferOffset		= 0;
1671 	const VkClearValue						attachmentClearValue	= makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f);
1672 	const deUint32							attachmentCount			= 1 + testParams.makeCopy + isColorImageMultisampled;
1673 	const std::vector<VkClearValue>			attachmentClearValues	(attachmentCount, attachmentClearValue);
1674 
1675 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1676 
1677 	// First render pass - render dynamic density map
1678 	if (testParams.dynamicDensityMap)
1679 	{
1680 		std::vector<VkClearValue>	attachmentClearValuesDDM { makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f) };
1681 		const VkRenderPassBeginInfo renderPassBeginInfoProduceDynamicDensityMap
1682 		{
1683 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,							// VkStructureType		sType;
1684 			DE_NULL,															// const void*			pNext;
1685 			*m_renderPassProduceDynamicDensityMap,								// VkRenderPass			renderPass;
1686 			*m_framebufferProduceDynamicDensityMap,								// VkFramebuffer		framebuffer;
1687 			makeRect2D(densityMapImageSize.width, densityMapImageSize.height),	// VkRect2D				renderArea;
1688 			static_cast<deUint32>(attachmentClearValuesDDM.size()),				// uint32_t				clearValueCount;
1689 			attachmentClearValuesDDM.data()										// const VkClearValue*	pClearValues;
1690 		};
1691 		RPS2::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfoProduceDynamicDensityMap, &subpassBeginInfo);
1692 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineProduceDynamicDensityMap);
1693 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBufferDDM.get(), &vertexBufferOffset);
1694 		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_verticesDDM.size(), 1, 0, 0);
1695 		RPS2::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
1696 	}
1697 
1698 	// Render subsampled image
1699 	const VkRenderPassBeginInfo renderPassBeginInfoProduceSubsampledImage
1700 	{
1701 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,						// VkStructureType		sType;
1702 		DE_NULL,														// const void*			pNext;
1703 		*m_renderPassProduceSubsampledImage,							// VkRenderPass			renderPass;
1704 		*m_framebufferProduceSubsampledImage,							// VkFramebuffer		framebuffer;
1705 		makeRect2D(colorImageSize.width, colorImageSize.height),		// VkRect2D				renderArea;
1706 		static_cast<deUint32>(attachmentClearValues.size()),			// uint32_t				clearValueCount;
1707 		attachmentClearValues.data()									// const VkClearValue*	pClearValues;
1708 	};
1709 	RPS2::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfoProduceSubsampledImage, &subpassBeginInfo);
1710 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineProduceSubsampledImage);
1711 	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1712 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
1713 	if (testParams.makeCopy)
1714 	{
1715 		RPS2::cmdNextSubpass(vk, *m_cmdBuffer, &subpassBeginInfo, &subpassEndInfo);
1716 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineCopySubsampledImage);
1717 		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutOperateOnSubsampledImage, 0, 1, &m_descriptorSetOperateOnSubsampledImage.get(), 0, DE_NULL);
1718 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1719 		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
1720 	}
1721 	RPS2::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
1722 
1723 	// Resample subsampled image
1724 	if (testParams.subsampledLoads)
1725 	{
1726 		const VkRenderPassBeginInfo renderPassBeginInfoUpdateSubsampledImage
1727 		{
1728 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,					// VkStructureType		sType;
1729 			DE_NULL,													// const void*			pNext;
1730 			*m_renderPassUpdateSubsampledImage,							// VkRenderPass			renderPass;
1731 			*m_framebufferUpdateSubsampledImage,						// VkFramebuffer		framebuffer;
1732 			makeRect2D(colorImageSize.width, colorImageSize.height),	// VkRect2D				renderArea;
1733 			0u,															// uint32_t				clearValueCount;
1734 			DE_NULL														// const VkClearValue*	pClearValues;
1735 		};
1736 		RPS2::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfoUpdateSubsampledImage, &subpassBeginInfo);
1737 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineUpdateSubsampledImage);
1738 		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutOperateOnSubsampledImage, 0, 1, &m_descriptorSetOperateOnSubsampledImage.get(), 0, DE_NULL);
1739 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1740 		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
1741 		RPS2::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
1742 	}
1743 
1744 	// Copy subsampled image to normal image using sampler that is able to read from subsampled images
1745 	// (subsampled image cannot be copied using vkCmdCopyImageToBuffer)
1746 	const VkRenderPassBeginInfo renderPassBeginInfoOutputSubsampledImage
1747 	{
1748 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,							// VkStructureType		sType;
1749 		DE_NULL,															// const void*			pNext;
1750 		*m_renderPassOutputSubsampledImage,									// VkRenderPass			renderPass;
1751 		*m_framebufferOutputSubsampledImage,								// VkFramebuffer		framebuffer;
1752 		makeRect2D(outputImageSize.width, outputImageSize.height),			// VkRect2D				renderArea;
1753 		static_cast<deUint32>(attachmentClearValues.size()),				// uint32_t				clearValueCount;
1754 		attachmentClearValues.data()										// const VkClearValue*	pClearValues;
1755 	};
1756 	RPS2::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfoOutputSubsampledImage, &subpassBeginInfo);
1757 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineOutputSubsampledImage);
1758 	vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutOutputSubsampledImage, 0, 1, &m_descriptorSetOutputSubsampledImage.get(), 0, DE_NULL);
1759 	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBufferOutput.get(), &vertexBufferOffset);
1760 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_verticesOutput.size(), 1, 0, 0);
1761 	RPS2::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
1762 
1763 	endCommandBuffer(vk, *m_cmdBuffer);
1764 }
1765 
iterate(void)1766 tcu::TestStatus FragmentDensityMapTestInstance::iterate (void)
1767 {
1768 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1769 	const VkDevice			vkDevice	= getDevice(m_context);
1770 	const VkQueue			queue		= getDeviceQueue(vk, vkDevice, m_context.getUniversalQueueFamilyIndex(), 0);
1771 
1772 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1773 
1774 	// approximations used when coarse reconstruction is specified are implementation defined
1775 	if (m_testParams.coarseReconstruction)
1776 		return tcu::TestStatus::pass("Pass");
1777 
1778 	return verifyImage();
1779 }
1780 
1781 struct Vec4Sorter
1782 {
operator ()vkt::renderpass::__anonabc573560111::Vec4Sorter1783 	bool operator()(const tcu::Vec4& lhs, const tcu::Vec4& rhs) const
1784 	{
1785 		if (lhs.x() != rhs.x())
1786 			return lhs.x() < rhs.x();
1787 		if (lhs.y() != rhs.y())
1788 			return lhs.y() < rhs.y();
1789 		if (lhs.z() != rhs.z())
1790 			return lhs.z() < rhs.z();
1791 		return lhs.w() < rhs.w();
1792 	}
1793 };
1794 
verifyImage(void)1795 tcu::TestStatus FragmentDensityMapTestInstance::verifyImage (void)
1796 {
1797 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
1798 	const VkDevice						vkDevice			= getDevice(m_context);
1799 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1800 	const VkQueue						queue				= getDeviceQueue(vk, vkDevice, queueFamilyIndex, 0);
1801 	SimpleAllocator						memAlloc			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1802 	tcu::UVec2							renderSize			(m_renderSize.x(), m_renderSize.y());
1803 	de::UniquePtr<tcu::TextureLevel>	outputImage			(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_outputImage, VK_FORMAT_R8G8B8A8_UNORM, renderSize).release());
1804 	const tcu::ConstPixelBufferAccess&	outputAccess		(outputImage->getAccess());
1805 	tcu::TestLog&						log					(m_context.getTestContext().getLog());
1806 
1807 	// Log images
1808 	log << tcu::TestLog::ImageSet("Result", "Result images")
1809 		<< tcu::TestLog::Image("Rendered", "Rendered output image", outputAccess)
1810 		<< tcu::TestLog::EndImageSet;
1811 
1812 	deUint32	estimatedColorCount	= m_testParams.viewCount * m_testParams.fragmentArea.x() * m_testParams.fragmentArea.y();
1813 	float		densityMult			= m_densityValue.x() * m_densityValue.y();
1814 
1815 #if DRY_RUN_WITHOUT_FDM_EXTENSION
1816 	estimatedColorCount = m_testParams.viewCount + 2;
1817 	densityMult			= 0.0f;
1818 #endif
1819 
1820 	// Create histogram of all image colors, check the value of inverted FragSizeEXT
1821 	std::map<tcu::Vec4, deUint32, Vec4Sorter> colorCount;
1822 	for (int y = 0; y < outputAccess.getHeight(); y++)
1823 	{
1824 		for (int x = 0; x < outputAccess.getWidth(); x++)
1825 		{
1826 			tcu::Vec4	outputColor		= outputAccess.getPixel(x, y);
1827 			float		densityClamped	= outputColor.z() * outputColor.w();
1828 
1829 			if ((densityClamped + 0.01) < densityMult)
1830 				return tcu::TestStatus::fail("Wrong value of FragSizeEXT variable");
1831 
1832 			auto it = colorCount.find(outputColor);
1833 			if (it == end(colorCount))
1834 				it = colorCount.insert({ outputColor, 0u }).first;
1835 			it->second++;
1836 		}
1837 	}
1838 
1839 	// Check if color count is the same as estimated one
1840 	for (const auto& color : colorCount)
1841 	{
1842 		if (color.second > estimatedColorCount)
1843 			return tcu::TestStatus::fail("Wrong color count");
1844 	}
1845 
1846 	return tcu::TestStatus::pass("Pass");
1847 }
1848 
1849 } // anonymous
1850 
createChildren(tcu::TestCaseGroup * fdmTests)1851 static void createChildren (tcu::TestCaseGroup* fdmTests)
1852 {
1853 	tcu::TestContext&	testCtx		= fdmTests->getTestContext();
1854 
1855 	const struct
1856 	{
1857 		std::string		name;
1858 		deUint32		viewCount;
1859 	} views[] =
1860 	{
1861 		{ "1_view",		1 },
1862 		{ "2_views",	2 },
1863 		{ "4_views",	4 },
1864 		{ "6_views",	6 },
1865 	};
1866 
1867 	const struct
1868 	{
1869 		std::string			name;
1870 		bool				makeCopy;
1871 	} renders[] =
1872 	{
1873 		{ "render",			false },
1874 		{ "render_copy",	true }
1875 	};
1876 
1877 	const struct
1878 	{
1879 		std::string		name;
1880 		float			renderSizeToDensitySize;
1881 	} sizes[] =
1882 	{
1883 		{ "divisible_density_size",		4.0f },
1884 		{ "non_divisible_density_size",	3.75f }
1885 	};
1886 
1887 	const struct
1888 	{
1889 		std::string				name;
1890 		VkSampleCountFlagBits	samples;
1891 	} samples[] =
1892 	{
1893 		{ "1_sample",	VK_SAMPLE_COUNT_1_BIT },
1894 		{ "2_samples",	VK_SAMPLE_COUNT_2_BIT },
1895 		{ "4_samples",	VK_SAMPLE_COUNT_4_BIT },
1896 		{ "8_samples",	VK_SAMPLE_COUNT_8_BIT }
1897 	};
1898 
1899 	std::vector<tcu::UVec2> fragmentArea
1900 	{
1901 		{ 1, 2 },
1902 		{ 2, 1 },
1903 		{ 2, 2 }
1904 	};
1905 
1906 	for (const auto& view : views)
1907 	{
1908 		de::MovePtr<tcu::TestCaseGroup> viewGroup(new tcu::TestCaseGroup(testCtx, view.name.c_str(), ""));
1909 		for (const auto& render : renders)
1910 		{
1911 			de::MovePtr<tcu::TestCaseGroup> renderGroup(new tcu::TestCaseGroup(testCtx, render.name.c_str(), ""));
1912 			for (const auto& size : sizes)
1913 			{
1914 				de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, size.name.c_str(), ""));
1915 				for (const auto& sample : samples)
1916 				{
1917 					de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sample.name.c_str(), ""));
1918 					for (const auto& area : fragmentArea)
1919 					{
1920 						std::stringstream str;
1921 						str << "_" << area.x() << "_" << area.y();
1922 
1923 						TestParams params
1924 						{
1925 							false,							// bool						dynamicDensityMap;
1926 							false,							// bool						deferredDensityMap;
1927 							false,							// bool						nonSubsampledImages;
1928 							false,							// bool						subsampledLoads;
1929 							false,							// bool						coarseReconstruction;
1930 							1,								// deUint32					samplersCount;
1931 							view.viewCount,					// deUint32					viewCount;
1932 							render.makeCopy,				// bool						makeCopy;
1933 							size.renderSizeToDensitySize,	// float					renderMultiplier;
1934 							sample.samples,					// VkSampleCountFlagBits	colorSamples;
1935 							area,							// tcu::UVec2				fragmentArea;
1936 							{ 16, 16 },						// tcu::UVec2				densityMapSize;
1937 							VK_FORMAT_R8G8_UNORM			// VkFormat					densityMapFormat;
1938 						};
1939 
1940 						sampleGroup->addChild(new FragmentDensityMapTest(testCtx, std::string("static_subsampled") + str.str(), "", params));
1941 						params.deferredDensityMap	= true;
1942 						sampleGroup->addChild(new FragmentDensityMapTest(testCtx, std::string("deferred_subsampled") + str.str(), "", params));
1943 						params.deferredDensityMap	= false;
1944 						params.dynamicDensityMap	= true;
1945 						sampleGroup->addChild(new FragmentDensityMapTest(testCtx, std::string("dynamic_subsampled") + str.str(), "", params));
1946 
1947 						// generate nonsubsampled tests just for single view and double view cases
1948 						if (view.viewCount < 3)
1949 						{
1950 							params.nonSubsampledImages	= true;
1951 							sampleGroup->addChild(new FragmentDensityMapTest(testCtx, std::string("static_nonsubsampled") + str.str(), "", params));
1952 							params.deferredDensityMap	= true;
1953 							sampleGroup->addChild(new FragmentDensityMapTest(testCtx, std::string("deferred_nonsubsampled") + str.str(), "", params));
1954 							params.deferredDensityMap	= false;
1955 							params.dynamicDensityMap	= true;
1956 							sampleGroup->addChild(new FragmentDensityMapTest(testCtx, std::string("dynamic_nonsubsampled") + str.str(), "", params));
1957 						}
1958 					}
1959 					sizeGroup->addChild(sampleGroup.release());
1960 				}
1961 				renderGroup->addChild(sizeGroup.release());
1962 			}
1963 			viewGroup->addChild(renderGroup.release());
1964 		}
1965 		fdmTests->addChild(viewGroup.release());
1966 	}
1967 
1968 	const struct
1969 	{
1970 		std::string		name;
1971 		deUint32		count;
1972 	} subsampledSamplers[] =
1973 	{
1974 		{ "2_subsampled_samplers",	2 },
1975 		{ "4_subsampled_samplers",	4 },
1976 		{ "6_subsampled_samplers",	6 },
1977 		{ "8_subsampled_samplers",	8 }
1978 	};
1979 
1980 	de::MovePtr<tcu::TestCaseGroup> propertiesGroup(new tcu::TestCaseGroup(testCtx, "properties", ""));
1981 	for (const auto& sampler : subsampledSamplers)
1982 	{
1983 		TestParams params
1984 		{
1985 			false,							// bool						dynamicDensityMap;
1986 			false,							// bool						deferredDensityMap;
1987 			false,							// bool						nonSubsampledImages;
1988 			false,							// bool						subsampledLoads;
1989 			false,							// bool						coarseReconstruction;
1990 			sampler.count,					// deUint32					samplersCount;
1991 			1,								// deUint32					viewCount;
1992 			false,							// bool						makeCopy;
1993 			4.0f,							// float					renderMultiplier;
1994 			VK_SAMPLE_COUNT_1_BIT,			// VkSampleCountFlagBits	colorSamples;
1995 			{  2,  2 },						// tcu::UVec2				fragmentArea;
1996 			{ 16, 16 },						// tcu::UVec2				densityMapSize;
1997 			VK_FORMAT_R8G8_UNORM			// VkFormat					densityMapFormat;
1998 		};
1999 		propertiesGroup->addChild(new FragmentDensityMapTest(testCtx, sampler.name, "", params));
2000 	}
2001 	TestParams params
2002 	{
2003 		false,							// bool						dynamicDensityMap;
2004 		false,							// bool						deferredDensityMap;
2005 		false,							// bool						nonSubsampledImages;
2006 		true,							// bool						subsampledLoads;
2007 		false,							// bool						coarseReconstruction;
2008 		1,								// deUint32					samplersCount;
2009 		2,								// deUint32					viewCount;
2010 		false,							// bool						makeCopy;
2011 		4.0f,							// float					renderMultiplier;
2012 		VK_SAMPLE_COUNT_1_BIT,			// VkSampleCountFlagBits	colorSamples;
2013 		{  1,  2 },						// tcu::UVec2				fragmentArea;
2014 		{ 16, 16 },						// tcu::UVec2				densityMapSize;
2015 		VK_FORMAT_R8G8_UNORM			// VkFormat					densityMapFormat;
2016 	};
2017 	propertiesGroup->addChild(new FragmentDensityMapTest(testCtx, "subsampled_loads", "", params));
2018 	params.subsampledLoads		= false;
2019 	params.coarseReconstruction	= true;
2020 	propertiesGroup->addChild(new FragmentDensityMapTest(testCtx, "subsampled_coarse_reconstruction", "", params));
2021 	fdmTests->addChild(propertiesGroup.release());
2022 }
2023 
cleanupGroup(tcu::TestCaseGroup * group)2024 static void cleanupGroup (tcu::TestCaseGroup* group)
2025 {
2026 	DE_UNREF(group);
2027 	// Destroy singleton objects.
2028 	g_singletonDevice.clear();
2029 }
2030 
createFragmentDensityMapTests(tcu::TestContext & testCtx)2031 tcu::TestCaseGroup* createFragmentDensityMapTests (tcu::TestContext& testCtx)
2032 {
2033 	return createTestGroup(testCtx, "fragment_density_map", "VK_EXT_fragment_density_map and VK_EXT_fragment_density_map2 extensions tests", createChildren, cleanupGroup);
2034 }
2035 
2036 } // renderpass
2037 
2038 } // vkt
2039