• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 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 for VK_KHR_fragment_shading_rate
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktAttachmentRateTests.hpp"
25 
26 #include "vkBufferWithMemory.hpp"
27 #include "vkImageWithMemory.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkBarrierUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkPlatform.hpp"
36 #include "vkBuilderUtil.hpp"
37 
38 #include "vktTestGroupUtil.hpp"
39 #include "vktTestCase.hpp"
40 #include "vktCustomInstancesDevices.hpp"
41 
42 #include "deDefs.h"
43 #include "deMath.h"
44 #include "deSharedPtr.hpp"
45 #include "deString.h"
46 #include "deSTLUtil.hpp"
47 
48 #include "tcuTestCase.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuTextureUtil.hpp"
51 #include "tcuStringTemplate.hpp"
52 
53 #include <string>
54 #include <vector>
55 #include <limits>
56 #include <map>
57 
58 namespace vkt
59 {
60 namespace FragmentShadingRate
61 {
62 namespace
63 {
64 
65 using namespace vk;
66 
67 // flag used to test TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER;
68 // when it is 1 instead of using atomic operations to fill image
69 // plain store will be used as it is always supported
70 #define DEBUG_USE_STORE_INSTEAD_OF_ATOMICS 0
71 
72 enum TestMode
73 {
74 	TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER = 0,
75 	TM_SETUP_RATE_WITH_FRAGMENT_SHADER,
76 	TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE,
77 	TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,
78 	TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,
79 	TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE,
80 
81 	TM_TWO_SUBPASS
82 };
83 
84 struct TestParams
85 {
86 	TestMode		mode;
87 
88 	VkFormat		srFormat;
89 	VkExtent2D		srRate;
90 
91 	bool			useImagelessFramebuffer;
92 };
93 
calculateRate(deUint32 rateWidth,deUint32 rateHeight)94 deUint32 calculateRate(deUint32 rateWidth, deUint32 rateHeight)
95 {
96 	return (deCtz32(rateWidth) << 2u) | deCtz32(rateHeight);
97 }
98 
99 class AttachmentRateInstance : public TestInstance
100 {
101 public:
102 							AttachmentRateInstance	(Context& context, const de::SharedPtr<TestParams> params);
103 	tcu::TestStatus			iterate					(void);
104 
105 private:
106 
107 	// Helper structure used by buildFramebuffer method.
108 	// It is used to build regular or imageless framebuffer.
109 	struct FBAttachmentInfo
110 	{
111 		VkFormat			format;
112 		VkImageUsageFlags	usage;
113 		deUint32			width;
114 		deUint32			height;
115 		VkImageView			view;
116 	};
117 
118 private:
119 
120 	de::MovePtr<ImageWithMemory>	buildImageWithMemory		(VkFormat						format,
121 																 deUint32						width,
122 																 deUint32						height,
123 																 VkImageUsageFlags				usage,
124 																 VkImageTiling					tiling = VK_IMAGE_TILING_OPTIMAL,
125 																 std::vector<deUint32>			queueFamilies = std::vector<deUint32>());
126 	de::MovePtr<BufferWithMemory>	buildBufferWithMemory		(deUint32						size,
127 																 VkBufferUsageFlags				usage);
128 	Move<VkImageView>				buildImageView				(VkFormat						format,
129 																 VkImage						image);
130 
131 	void							buildColorBufferObjects		(deUint32						cbIindex,
132 																 VkImageUsageFlags				cbUsage);
133 	void							buildShadingRateObjects		(deUint32						srIndex,
134 																 deUint32						width,
135 																 deUint32						height,
136 																 VkImageUsageFlags				srUsage,
137 																 VkImageTiling					srTiling = VK_IMAGE_TILING_OPTIMAL);
138 	void							buildCounterBufferObjects	();
139 
140 	Move<VkRenderPass>				buildRenderPass				(VkFormat								cbFormat,
141 																 deUint32								sr1TileWidth = 0,
142 																 deUint32								sr1TileHeight = 0,
143 																 deUint32								sr2TileWidth = 0,
144 																 deUint32								sr2TileHeight = 0) const;
145 	Move<VkFramebuffer>				buildFramebuffer			(VkRenderPass							renderPass,
146 																 const std::vector<FBAttachmentInfo>&	attachmentInfo) const;
147 	Move<VkPipelineLayout>			buildPipelineLayout			(const VkDescriptorSetLayout*			setLayouts = DE_NULL) const;
148 	Move<VkPipeline>				buildGraphicsPipeline		(deUint32								subpass,
149 																 VkRenderPass							renderPass,
150 																 VkPipelineLayout						layout,
151 																 VkShaderModule							vertShader,
152 																 VkShaderModule							fragShader,
153 																 bool									useShadingRate = VK_TRUE) const;
154 	Move<VkPipeline>				buildComputePipeline		(VkShaderModule							compShader,
155 																 VkPipelineLayout						pipelineLayout) const;
156 	VkDescriptorSetAllocateInfo		makeDescriptorSetAllocInfo	(VkDescriptorPool						descriptorPool,
157 																 const VkDescriptorSetLayout*			pSetLayouts) const;
158 
159 	void							startRendering				(const VkCommandBuffer					commandBuffer,
160 																 const VkRenderPass						renderPass,
161 																 const VkFramebuffer					framebuffer,
162 																 const VkRect2D&						renderArea,
163 																 const std::vector<FBAttachmentInfo>&	attachmentInfo) const;
164 	void							finishRendering				(const VkCommandBuffer					commandBuffer) const;
165 
166 	bool							verifyUsingAtomicChecks		(deUint32						tileWidth,
167 																 deUint32						tileHeight,
168 																 deUint32						rateWidth,
169 																 deUint32						rateHeight,
170 																 deUint32*						outBufferPtr) const;
171 
172 	bool							runComputeShaderMode		(void);
173 	bool							runFragmentShaderMode		(void);
174 	bool							runCopyMode					(void);
175 	bool							runCopyModeOnTransferQueue	(void);
176 	bool							runFillLinearTiledImage		(void);
177 	bool							runTwoSubpassMode			(void);
178 
179 private:
180 
181 	// When custom device is used then m_device and m_allocator are used in all
182 	// helper methods. Otherwise default device and allocator from context are used.
183 	// Those objects are used only by tests from runCopyModeOnTransferQueue.
184 	Move<VkDevice>					m_device;
185 	de::MovePtr<Allocator>			m_allocator;
186 
187 	const de::SharedPtr<TestParams>	m_params;
188 	const deUint32					m_cbWidth;
189 	const deUint32					m_cbHeight;
190 	VkFormat						m_cbFormat;
191 	VkImageUsageFlags				m_cbUsage;
192 	VkImageUsageFlags				m_srUsage;
193 
194 	// structures commonly used by most of tests
195 	const VkImageSubresourceLayers	m_defaultImageSubresourceLayers;
196 	const VkImageSubresourceRange	m_defaultImageSubresourceRange;
197 	const VkBufferImageCopy			m_defaultBufferImageCopy;
198 
199 	// objects commonly used by most of tests
200 	de::MovePtr<ImageWithMemory>	m_cbImage[2];
201 	Move<VkImageView>				m_cbImageView[2];
202 	de::MovePtr<BufferWithMemory>	m_cbReadBuffer[2];
203 
204 	de::MovePtr<ImageWithMemory>	m_srImage[2];
205 	Move<VkImageView>				m_srImageView[2];
206 
207 	Move<VkDescriptorSetLayout>		m_counterBufferDescriptorSetLayout;
208 	Move<VkDescriptorPool>			m_counterBufferDescriptorPool;
209 	Move<VkDescriptorSet>			m_counterBufferDescriptorSet;
210 	de::MovePtr<BufferWithMemory>	m_counterBuffer;
211 
212 	// properties commonly used by most of tests
213 	VkExtent2D						m_minTileSize;
214 	VkExtent2D						m_maxTileSize;
215 	deUint32						m_maxAspectRatio;
216 };
217 
AttachmentRateInstance(Context & context,const de::SharedPtr<TestParams> params)218 AttachmentRateInstance::AttachmentRateInstance(Context& context, const de::SharedPtr<TestParams> params)
219 	: vkt::TestInstance					(context)
220 	, m_params							(params)
221 	, m_cbWidth							(60)
222 	, m_cbHeight						(60)
223 	, m_cbFormat						(VK_FORMAT_R32G32B32A32_UINT)
224 	, m_cbUsage							(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
225 	, m_srUsage							(VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
226 	, m_defaultImageSubresourceLayers	(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
227 	, m_defaultImageSubresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u))
228 	, m_defaultBufferImageCopy			(makeBufferImageCopy({ m_cbWidth, m_cbHeight, 1u }, m_defaultImageSubresourceLayers))
229 {
230 	// prepare data needed to calculate tile sizes
231 	const auto& srProperties	= m_context.getFragmentShadingRateProperties();
232 	m_minTileSize				= srProperties.minFragmentShadingRateAttachmentTexelSize;
233 	m_maxTileSize				= srProperties.maxFragmentShadingRateAttachmentTexelSize;
234 	m_maxAspectRatio			= srProperties.maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
235 }
236 
buildImageWithMemory(VkFormat format,deUint32 width,deUint32 height,VkImageUsageFlags usage,VkImageTiling tiling,std::vector<deUint32> queueFamilies)237 de::MovePtr<ImageWithMemory> AttachmentRateInstance::buildImageWithMemory (VkFormat					format,
238 																		   deUint32					width,
239 																		   deUint32					height,
240 																		   VkImageUsageFlags		usage,
241 																		   VkImageTiling			tiling,
242 																		   std::vector<deUint32>	queueFamilies)
243 {
244 	VkImageCreateInfo imageCreateInfo
245 	{
246 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
247 		DE_NULL,									// const void*				pNext;
248 		(VkImageCreateFlags)0u,						// VkImageCreateFlags		flags;
249 		VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
250 		format,										// VkFormat					format;
251 		{
252 			width,									// deUint32					width;
253 			height,									// deUint32					height;
254 			1u										// deUint32					depth;
255 		},											// VkExtent3D				extent;
256 		1u,											// deUint32					mipLevels;
257 		1u,											// deUint32					arrayLayers;
258 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
259 		tiling,										// VkImageTiling			tiling;
260 		usage,										// VkImageUsageFlags		usage;
261 		queueFamilies.empty() ?
262 			VK_SHARING_MODE_EXCLUSIVE :
263 			VK_SHARING_MODE_CONCURRENT,				// VkSharingMode			sharingMode;
264 		(deUint32)queueFamilies.size(),				// deUint32					queueFamilyIndexCount;
265 		queueFamilies.data(),						// const deUint32*			pQueueFamilyIndices;
266 		VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
267 	};
268 
269 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
270 	VkDevice				device				= m_device.get() ? *m_device : m_context.getDevice();
271 	vk::Allocator&			allocator			= m_allocator.get() ? *m_allocator : m_context.getDefaultAllocator();
272 	vk::MemoryRequirement	memoryRequirement	= (tiling == VK_IMAGE_TILING_LINEAR) ? MemoryRequirement::HostVisible : MemoryRequirement::Any;
273 	return de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, memoryRequirement));
274 }
275 
buildBufferWithMemory(deUint32 size,VkBufferUsageFlags usage)276 de::MovePtr<BufferWithMemory> AttachmentRateInstance::buildBufferWithMemory(deUint32 size, VkBufferUsageFlags usage)
277 {
278 	const DeviceInterface&		vk				= m_context.getDeviceInterface();
279 	VkDevice					device			= m_device.get() ? *m_device : m_context.getDevice();
280 	vk::Allocator&				allocator		= m_allocator.get() ? *m_allocator : m_context.getDefaultAllocator();
281 	const VkBufferCreateInfo	readBufferInfo	= makeBufferCreateInfo(size, usage);
282 
283 	return de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, readBufferInfo, MemoryRequirement::HostVisible));
284 }
285 
buildImageView(VkFormat format,VkImage image)286 Move<VkImageView> AttachmentRateInstance::buildImageView (VkFormat format, VkImage image)
287 {
288 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
289 	VkDevice				device				= m_device.get() ? *m_device : m_context.getDevice();
290 	VkImageSubresourceRange	subresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
291 
292 	return makeImageView(vk, device, image, VK_IMAGE_VIEW_TYPE_2D, format, subresourceRange);
293 };
294 
buildColorBufferObjects(deUint32 cbIndex,VkImageUsageFlags cbUsage)295 void AttachmentRateInstance::buildColorBufferObjects(deUint32 cbIndex, VkImageUsageFlags cbUsage)
296 {
297 	DE_ASSERT(cbIndex < 2);
298 
299 	m_cbImage[cbIndex]			= buildImageWithMemory(m_cbFormat, m_cbWidth, m_cbHeight, cbUsage);
300 	m_cbImageView[cbIndex]		= buildImageView(m_cbFormat, m_cbImage[cbIndex]->get());
301 	m_cbReadBuffer[cbIndex]		= buildBufferWithMemory(m_cbWidth * m_cbHeight * deUint32(sizeof(int)) * 4u, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
302 }
303 
buildShadingRateObjects(deUint32 srIndex,deUint32 width,deUint32 height,VkImageUsageFlags srUsage,VkImageTiling srTiling)304 void AttachmentRateInstance::buildShadingRateObjects(deUint32 srIndex, deUint32 width, deUint32 height, VkImageUsageFlags srUsage, VkImageTiling srTiling)
305 {
306 	DE_ASSERT(srIndex < 2);
307 
308 	m_srImage[srIndex]		= buildImageWithMemory(m_params->srFormat, width, height, srUsage, srTiling);
309 	m_srImageView[srIndex]	= buildImageView(m_params->srFormat, m_srImage[srIndex]->get());
310 }
311 
buildCounterBufferObjects()312 void AttachmentRateInstance::buildCounterBufferObjects()
313 {
314 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
315 	VkDevice				device	= m_device.get() ? *m_device : m_context.getDevice();
316 
317 	m_counterBufferDescriptorPool		= DescriptorPoolBuilder()
318 											.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
319 											.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
320 	m_counterBufferDescriptorSetLayout	= DescriptorSetLayoutBuilder()
321 											.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
322 											.build(vk, device);
323 
324 	const VkDescriptorSetAllocateInfo descriptorSetAllocInfo = makeDescriptorSetAllocInfo(*m_counterBufferDescriptorPool,
325 																						  &(*m_counterBufferDescriptorSetLayout));
326 	m_counterBufferDescriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
327 
328 	// create ssbo buffer for atomic counter
329 	deUint32 ssboSize	= deUint32(sizeof(deUint32));
330 	m_counterBuffer		= buildBufferWithMemory(ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
331 
332 	const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(**m_counterBuffer, 0, ssboSize);
333 	DescriptorSetUpdateBuilder()
334 		.writeSingle(*m_counterBufferDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
335 		.update(vk, device);
336 
337 	// reset counter
338 	*((deUint32*)m_counterBuffer->getAllocation().getHostPtr()) = 0u;
339 	flushAlloc(vk, device, m_counterBuffer->getAllocation());
340 }
341 
buildRenderPass(VkFormat cbFormat,deUint32 sr0TileWidth,deUint32 sr0TileHeight,deUint32 sr1TileWidth,deUint32 sr1TileHeight) const342 Move<VkRenderPass> AttachmentRateInstance::buildRenderPass(VkFormat cbFormat,
343 														   deUint32 sr0TileWidth, deUint32 sr0TileHeight,
344 														   deUint32 sr1TileWidth, deUint32 sr1TileHeight) const
345 {
346 	const bool		useShadingRate0		= (sr0TileWidth * sr0TileHeight > 0);
347 	const bool		useShadingRate1		= (sr1TileWidth * sr1TileHeight > 0);
348 
349 	deUint32		attachmentCount		= 1;
350 	const deUint32	subpassCount		= 1 + useShadingRate1;
351 
352 	std::vector<VkAttachmentReference2> colorAttachmentReferences(subpassCount, {
353 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,							// VkStructureType					sType;
354 		DE_NULL,															// const void*						pNext;
355 		0,																	// uint32_t							attachment;
356 		VK_IMAGE_LAYOUT_GENERAL,											// VkImageLayout					layout;
357 		0,																	// VkImageAspectFlags				aspectMask;
358 	});
359 
360 	std::vector<VkAttachmentReference2> fragmentShadingRateAttachments(subpassCount, {
361 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,							// VkStructureType					sType;
362 		DE_NULL,															// const void*						pNext;
363 		1,																	// uint32_t							attachment;
364 		VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,		// VkImageLayout					layout;
365 		0,																	// VkImageAspectFlags				aspectMask;
366 	});
367 
368 	std::vector<VkFragmentShadingRateAttachmentInfoKHR> shadingRateAttachmentInfos(subpassCount, {
369 		VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,		// VkStructureType					sType;
370 		DE_NULL,															// const void*						pNext;
371 		&fragmentShadingRateAttachments[0],									// const VkAttachmentReference2*	pFragmentShadingRateAttachment;
372 		{ sr0TileWidth, sr0TileHeight },									// VkExtent2D						shadingRateAttachmentTexelSize;
373 	});
374 
375 	std::vector<VkSubpassDescription2> subpassDescriptions(subpassCount, {
376 		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,							// VkStructureType					sType;
377 		DE_NULL,															// const void*						pNext;
378 		(vk::VkSubpassDescriptionFlags)0,									// VkSubpassDescriptionFlags		flags;
379 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,								// VkPipelineBindPoint				pipelineBindPoint;
380 		0u,																	// uint32_t							viewMask;
381 		0u,																	// uint32_t							inputAttachmentCount;
382 		DE_NULL,															// const VkAttachmentReference2*	pInputAttachments;
383 		1,																	// uint32_t							colorAttachmentCount;
384 		&colorAttachmentReferences[0],										// const VkAttachmentReference2*	pColorAttachments;
385 		DE_NULL,															// const VkAttachmentReference2*	pResolveAttachments;
386 		DE_NULL,															// const VkAttachmentReference2*	pDepthStencilAttachment;
387 		0u,																	// uint32_t							preserveAttachmentCount;
388 		DE_NULL,															// const uint32_t*					pPreserveAttachments;
389 	});
390 
391 	std::vector<VkAttachmentDescription2> attachmentDescriptions(2 * subpassCount, {
392 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,							// VkStructureType					sType;
393 		DE_NULL,															// const void*						pNext;
394 		(VkAttachmentDescriptionFlags)0u,									// VkAttachmentDescriptionFlags		flags;
395 		cbFormat,															// VkFormat							format;
396 		VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagBits			samples;
397 		VK_ATTACHMENT_LOAD_OP_CLEAR,										// VkAttachmentLoadOp				loadOp;
398 		VK_ATTACHMENT_STORE_OP_STORE,										// VkAttachmentStoreOp				storeOp;
399 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,									// VkAttachmentLoadOp				stencilLoadOp;
400 		VK_ATTACHMENT_STORE_OP_DONT_CARE,									// VkAttachmentStoreOp				stencilStoreOp;
401 		VK_IMAGE_LAYOUT_GENERAL,											// VkImageLayout					initialLayout;
402 		VK_IMAGE_LAYOUT_GENERAL												// VkImageLayout					finalLayout;
403 	});
404 
405 	if (useShadingRate0)
406 	{
407 		attachmentCount							= 2;
408 		subpassDescriptions[0].pNext			= &shadingRateAttachmentInfos[0];
409 		attachmentDescriptions[1].format		= m_params->srFormat;
410 		attachmentDescriptions[1].loadOp		= VK_ATTACHMENT_LOAD_OP_LOAD;
411 		attachmentDescriptions[1].storeOp		= VK_ATTACHMENT_STORE_OP_DONT_CARE;
412 		attachmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
413 	}
414 
415 	if (useShadingRate1)
416 	{
417 		attachmentCount													= 4;
418 		colorAttachmentReferences[1].attachment							= 2;
419 		fragmentShadingRateAttachments[1].attachment					= 3;
420 		shadingRateAttachmentInfos[1].pFragmentShadingRateAttachment	= &fragmentShadingRateAttachments[1];
421 		shadingRateAttachmentInfos[1].shadingRateAttachmentTexelSize	= { sr1TileWidth, sr1TileHeight };
422 		subpassDescriptions[1].pNext									= &shadingRateAttachmentInfos[1];
423 		subpassDescriptions[1].pColorAttachments						= &colorAttachmentReferences[1];
424 
425 		attachmentDescriptions[3].format		= m_params->srFormat;
426 		attachmentDescriptions[3].loadOp		= VK_ATTACHMENT_LOAD_OP_LOAD;
427 		attachmentDescriptions[3].storeOp		= VK_ATTACHMENT_STORE_OP_DONT_CARE;
428 		attachmentDescriptions[3].initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
429 	}
430 
431 	const VkRenderPassCreateInfo2 renderPassParams
432 	{
433 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,						// VkStructureType					sType;
434 		DE_NULL,															// const void*						pNext;
435 		(vk::VkRenderPassCreateFlags)0,										// VkRenderPassCreateFlags			flags;
436 		attachmentCount,													// uint32_t							attachmentCount;
437 		attachmentDescriptions.data(),										// const VkAttachmentDescription2*	pAttachments;
438 		subpassCount,														// uint32_t							subpassCount;
439 		subpassDescriptions.data(),											// const VkSubpassDescription2*		pSubpasses;
440 		0u,																	// uint32_t							dependencyCount;
441 		DE_NULL,															// const VkSubpassDependency2*		pDependencies;
442 		0u,																	// uint32_t							correlatedViewMaskCount;
443 		DE_NULL,															// const uint32_t*					pCorrelatedViewMasks;
444 	};
445 
446 	VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
447 	return createRenderPass2(m_context.getDeviceInterface(), device, &renderPassParams);
448 }
449 
buildFramebuffer(VkRenderPass renderPass,const std::vector<FBAttachmentInfo> & attachmentInfo) const450 Move<VkFramebuffer> AttachmentRateInstance::buildFramebuffer(VkRenderPass renderPass, const std::vector<FBAttachmentInfo>& attachmentInfo) const
451 {
452 	VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
453 
454 	VkFramebufferCreateInfo framebufferParams
455 	{
456 		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,						// VkStructureType				sType;
457 		DE_NULL,															// const void*					pNext;
458 		(vk::VkFramebufferCreateFlags)0u,									// VkFramebufferCreateFlags		flags;
459 		renderPass,															// VkRenderPass					renderPass;
460 		(deUint32)attachmentInfo.size(),									// uint32_t						attachmentCount;
461 		DE_NULL,															// const VkImageView*			pAttachments;
462 		attachmentInfo[0].width,											// uint32_t						width;
463 		attachmentInfo[0].height,											// uint32_t						height;
464 		1u,																	// uint32_t						layers;
465 	};
466 
467 	if (m_params->useImagelessFramebuffer)
468 	{
469 		std::vector<VkFramebufferAttachmentImageInfo> framebufferAttachmentImageInfo(attachmentInfo.size(),
470 			{
471 				VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,		// VkStructureType		sType;
472 				DE_NULL,													// const void*			pNext;
473 				(VkImageCreateFlags)0u,										// VkImageCreateFlags	flags;
474 				0u,															// VkImageUsageFlags	usage;
475 				0u,															// deUint32				width;
476 				0u,															// deUint32				height;
477 				1u,															// deUint32				layerCount;
478 				1u,															// deUint32				viewFormatCount;
479 				DE_NULL														// const VkFormat*		pViewFormats;
480 			}
481 		);
482 
483 		for (deUint32 i = 0; i < (deUint32)attachmentInfo.size(); ++i)
484 		{
485 			const auto&	src = attachmentInfo[i];
486 			auto&		dst = framebufferAttachmentImageInfo[i];
487 
488 			dst.usage			= src.usage;
489 			dst.width			= src.width;
490 			dst.height			= src.height;
491 			dst.pViewFormats	= &src.format;
492 		}
493 
494 		VkFramebufferAttachmentsCreateInfo framebufferAttachmentsCreateInfo
495 		{
496 			VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO,			// VkStructureType							sType;
497 			DE_NULL,														// const void*								pNext;
498 			(deUint32)framebufferAttachmentImageInfo.size(),				// deUint32									attachmentImageInfoCount;
499 			framebufferAttachmentImageInfo.data()							// const VkFramebufferAttachmentImageInfo*	pAttachmentImageInfos;
500 		};
501 
502 		framebufferParams.pNext	= &framebufferAttachmentsCreateInfo;
503 		framebufferParams.flags	= VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
504 
505 		return createFramebuffer(m_context.getDeviceInterface(), device, &framebufferParams);
506 	}
507 
508 	// create array containing just attachment views
509 	std::vector<VkImageView> attachments(attachmentInfo.size(), 0);
510 	for (deUint32 i = 0; i < (deUint32)attachmentInfo.size(); ++i)
511 		attachments[i] = attachmentInfo[i].view;
512 
513 	framebufferParams.pAttachments = attachments.data();
514 
515 	return createFramebuffer(m_context.getDeviceInterface(), device, &framebufferParams);
516 }
517 
buildPipelineLayout(const VkDescriptorSetLayout * setLayouts) const518 Move<VkPipelineLayout> AttachmentRateInstance::buildPipelineLayout(const VkDescriptorSetLayout* setLayouts) const
519 {
520 	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo
521 	{
522 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
523 		DE_NULL,											// const void*						pNext;
524 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags		flags;
525 		(setLayouts != DE_NULL),							// uint32_t							setLayoutCount;
526 		setLayouts,											// const VkDescriptorSetLayout*		pSetLayouts;
527 		0u,													// uint32_t							pushConstantRangeCount;
528 		DE_NULL,											// const VkPushConstantRange*		pPushConstantRanges;
529 	};
530 
531 	VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
532 	return createPipelineLayout(m_context.getDeviceInterface(), device, &pipelineLayoutCreateInfo, NULL);
533 }
534 
buildGraphicsPipeline(deUint32 subpass,VkRenderPass renderPass,VkPipelineLayout pipelineLayout,VkShaderModule vertShader,VkShaderModule fragShader,bool useShadingRate) const535 Move<VkPipeline> AttachmentRateInstance::buildGraphicsPipeline(deUint32 subpass, VkRenderPass renderPass, VkPipelineLayout pipelineLayout,
536 															   VkShaderModule vertShader, VkShaderModule fragShader, bool useShadingRate) const
537 {
538 	std::vector<VkPipelineShaderStageCreateInfo> pipelineShaderStageParams(2,
539 	{
540 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,			// VkStructureType								sType
541 		DE_NULL,														// const void*									pNext
542 		0u,																// VkPipelineShaderStageCreateFlags				flags
543 		VK_SHADER_STAGE_VERTEX_BIT,										// VkShaderStageFlagBits						stage
544 		vertShader,														// VkShaderModule								module
545 		"main",															// const char*									pName
546 		DE_NULL															// const VkSpecializationInfo*					pSpecializationInfo
547 	});
548 
549 	pipelineShaderStageParams[1].stage	= VK_SHADER_STAGE_FRAGMENT_BIT;
550 	pipelineShaderStageParams[1].module	= fragShader;
551 
552 	const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo
553 	{
554 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType								sType
555 		DE_NULL,														// const void*									pNext
556 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags		flags
557 		0u,																// deUint32										vertexBindingDescriptionCount
558 		DE_NULL,														// const VkVertexInputBindingDescription*		pVertexBindingDescriptions
559 		0u,																// deUint32										vertexAttributeDescriptionCount
560 		DE_NULL															// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
561 	};
562 
563 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo
564 	{
565 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType								sType
566 		DE_NULL,														// const void*									pNext
567 		0u,																// VkPipelineInputAssemblyStateCreateFlags		flags
568 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,							// VkPrimitiveTopology							topology
569 		VK_FALSE														// VkBool32										primitiveRestartEnable
570 	};
571 
572 	tcu::UVec2	size		(m_cbWidth, m_cbHeight);
573 	VkViewport	viewport	= makeViewport	(size);
574 	VkRect2D	scissor		= makeRect2D	(size);
575 
576 	const VkPipelineViewportStateCreateInfo viewportStateCreateInfo
577 	{
578 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType								sType
579 		DE_NULL,														// const void*									pNext
580 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags			flags
581 		1u,																// deUint32										viewportCount
582 		&viewport,														// const VkViewport*							pViewports
583 		1u,																// deUint32										scissorCount
584 		&scissor														// const VkRect2D*								pScissors
585 	};
586 
587 	const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo
588 	{
589 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType								sType
590 		DE_NULL,														// const void*									pNext
591 		0u,																// VkPipelineRasterizationStateCreateFlags		flags
592 		VK_FALSE,														// VkBool32										depthClampEnable
593 		VK_FALSE,														// VkBool32										rasterizerDiscardEnable
594 		VK_POLYGON_MODE_FILL,											// VkPolygonMode								polygonMode
595 		VK_CULL_MODE_NONE,												// VkCullModeFlags								cullMode
596 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace									frontFace
597 		VK_FALSE,														// VkBool32										depthBiasEnable
598 		0.0f,															// float										depthBiasConstantFactor
599 		0.0f,															// float										depthBiasClamp
600 		0.0f,															// float										depthBiasSlopeFactor
601 		1.0f															// float										lineWidth
602 	};
603 
604 	const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
605 	{
606 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType								sType
607 		DE_NULL,														// const void*									pNext
608 		0u,																// VkPipelineMultisampleStateCreateFlags		flags
609 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits						rasterizationSamples
610 		VK_FALSE,														// VkBool32										sampleShadingEnable
611 		1.0f,															// float										minSampleShading
612 		DE_NULL,														// const VkSampleMask*							pSampleMask
613 		VK_FALSE,														// VkBool32										alphaToCoverageEnable
614 		VK_FALSE														// VkBool32										alphaToOneEnable
615 	};
616 
617 	const VkStencilOpState stencilOpState
618 	{
619 		VK_STENCIL_OP_KEEP,												// VkStencilOp									failOp
620 		VK_STENCIL_OP_KEEP,												// VkStencilOp									passOp
621 		VK_STENCIL_OP_KEEP,												// VkStencilOp									depthFailOp
622 		VK_COMPARE_OP_NEVER,											// VkCompareOp									compareOp
623 		0,																// deUint32										compareMask
624 		0,																// deUint32										writeMask
625 		0																// deUint32										reference
626 	};
627 
628 	const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo
629 	{
630 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType								sType
631 		DE_NULL,														// const void*									pNext
632 		0u,																// VkPipelineDepthStencilStateCreateFlags		flags
633 		VK_FALSE,														// VkBool32										depthTestEnable
634 		VK_FALSE,														// VkBool32										depthWriteEnable
635 		VK_COMPARE_OP_LESS_OR_EQUAL,									// VkCompareOp									depthCompareOp
636 		VK_FALSE,														// VkBool32										depthBoundsTestEnable
637 		VK_FALSE,														// VkBool32										stencilTestEnable
638 		stencilOpState,													// VkStencilOpState								front
639 		stencilOpState,													// VkStencilOpState								back
640 		0.0f,															// float										minDepthBounds
641 		1.0f,															// float										maxDepthBounds
642 	};
643 
644 	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState
645 	{
646 		VK_FALSE,														// VkBool32										blendEnable
647 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								srcColorBlendFactor
648 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								dstColorBlendFactor
649 		VK_BLEND_OP_ADD,												// VkBlendOp									colorBlendOp
650 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								srcAlphaBlendFactor
651 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								dstAlphaBlendFactor
652 		VK_BLEND_OP_ADD,												// VkBlendOp									alphaBlendOp
653 		VK_COLOR_COMPONENT_R_BIT										// VkColorComponentFlags						colorWriteMask
654 		| VK_COLOR_COMPONENT_G_BIT
655 		| VK_COLOR_COMPONENT_B_BIT
656 		| VK_COLOR_COMPONENT_A_BIT
657 	};
658 
659 	const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo
660 	{
661 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType
662 		DE_NULL,														// const void*									pNext
663 		0u,																// VkPipelineColorBlendStateCreateFlags			flags
664 		VK_FALSE,														// VkBool32										logicOpEnable
665 		VK_LOGIC_OP_CLEAR,												// VkLogicOp									logicOp
666 		1u,																// deUint32										attachmentCount
667 		&colorBlendAttachmentState,										// const VkPipelineColorBlendAttachmentState*	pAttachments
668 		{ 0.0f, 0.0f, 0.0f, 0.0f }										// float										blendConstants[4]
669 	};
670 
671 	const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo
672 	{
673 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,			// VkStructureType								sType
674 		DE_NULL,														// const void*									pNext
675 		0u,																// VkPipelineDynamicStateCreateFlags			flags
676 		0u,																// deUint32										dynamicStateCount
677 		DE_NULL															// const VkDynamicState*						pDynamicStates
678 	};
679 
680 	VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo
681 	{
682 		VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR,	// VkStructureType						sType;
683 		DE_NULL,																// const void*							pNext;
684 		{ 1, 1 },																// VkExtent2D							fragmentSize;
685 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
686 		  VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR }					// VkFragmentShadingRateCombinerOpKHR	combinerOps[2];
687 	};
688 
689 	const VkGraphicsPipelineCreateInfo pipelineCreateInfo
690 	{
691 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,				// VkStructureType									sType
692 		useShadingRate ? &shadingRateStateCreateInfo : DE_NULL,			// const void*										pNext
693 		0u,																// VkPipelineCreateFlags							flags
694 		(deUint32)pipelineShaderStageParams.size(),						// deUint32											stageCount
695 		&pipelineShaderStageParams[0],									// const VkPipelineShaderStageCreateInfo*			pStages
696 		&vertexInputStateCreateInfo,									// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState
697 		&inputAssemblyStateCreateInfo,									// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState
698 		DE_NULL,														// const VkPipelineTessellationStateCreateInfo*		pTessellationState
699 		&viewportStateCreateInfo,										// const VkPipelineViewportStateCreateInfo*			pViewportState
700 		&rasterizationStateCreateInfo,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState
701 		&multisampleStateCreateInfo,									// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState
702 		&depthStencilStateCreateInfo,									// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState
703 		&colorBlendStateCreateInfo,										// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState
704 		&dynamicStateCreateInfo,										// const VkPipelineDynamicStateCreateInfo*			pDynamicState
705 		pipelineLayout,													// VkPipelineLayout									layout
706 		renderPass,														// VkRenderPass										renderPass
707 		subpass,														// deUint32											subpass
708 		DE_NULL,														// VkPipeline										basePipelineHandle
709 		0																// deInt32											basePipelineIndex;
710 	};
711 
712 	VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
713 	return createGraphicsPipeline(m_context.getDeviceInterface(), device, DE_NULL, &pipelineCreateInfo);
714 }
715 
buildComputePipeline(VkShaderModule compShader,VkPipelineLayout pipelineLayout) const716 Move<VkPipeline> AttachmentRateInstance::buildComputePipeline(VkShaderModule compShader, VkPipelineLayout pipelineLayout) const
717 {
718 	const VkPipelineShaderStageCreateInfo stageCreateInfo
719 	{
720 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
721 		DE_NULL,												// const void*							pNext;
722 		0u,														// VkPipelineShaderStageCreateFlags		flags;
723 		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
724 		compShader,												// VkShaderModule						module;
725 		"main",													// const char*							pName;
726 		DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
727 	};
728 
729 	const VkComputePipelineCreateInfo createInfo
730 	{
731 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType						sType;
732 		DE_NULL,												// const void*							pNext;
733 		0u,														// VkPipelineCreateFlags				flags;
734 		stageCreateInfo,										// VkPipelineShaderStageCreateInfo		stage;
735 		pipelineLayout,											// VkPipelineLayout						layout;
736 		(VkPipeline)0,											// VkPipeline							basePipelineHandle;
737 		0u,														// int32_t								basePipelineIndex;
738 	};
739 
740 	VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
741 	return createComputePipeline(m_context.getDeviceInterface(), device, (vk::VkPipelineCache)0u, &createInfo);
742 }
743 
makeDescriptorSetAllocInfo(VkDescriptorPool descriptorPool,const VkDescriptorSetLayout * pSetLayouts) const744 VkDescriptorSetAllocateInfo AttachmentRateInstance::makeDescriptorSetAllocInfo(VkDescriptorPool descriptorPool, const VkDescriptorSetLayout* pSetLayouts) const
745 {
746 	return
747 	{
748 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType					sType;
749 		DE_NULL,											// const void*						pNext;
750 		descriptorPool,										// VkDescriptorPool					descriptorPool;
751 		1u,													// uint32_t							setLayoutCount;
752 		pSetLayouts,										// const VkDescriptorSetLayout*		pSetLayouts;
753 	};
754 }
755 
startRendering(const VkCommandBuffer commandBuffer,const VkRenderPass renderPass,const VkFramebuffer framebuffer,const VkRect2D & renderArea,const std::vector<FBAttachmentInfo> & attachmentInfo) const756 void AttachmentRateInstance::startRendering(const VkCommandBuffer					commandBuffer,
757 											const VkRenderPass						renderPass,
758 											const VkFramebuffer						framebuffer,
759 											const VkRect2D&							renderArea,
760 											const std::vector<FBAttachmentInfo>&	attachmentInfo) const
761 {
762 	const DeviceInterface&				vk								(m_context.getDeviceInterface());
763 	std::vector<VkClearValue>			clearColor						(attachmentInfo.size(), makeClearValueColorU32(0, 0, 0, 0));
764 	std::vector<VkImageView>			attachments						(attachmentInfo.size(), 0);
765 	VkRenderPassAttachmentBeginInfo		renderPassAttachmentBeginInfo;
766 	void*								pNext							(DE_NULL);
767 
768 	if (m_params->useImagelessFramebuffer)
769 	{
770 		// create array containing attachment views
771 		for (deUint32 i = 0; i < (deUint32)attachmentInfo.size(); ++i)
772 			attachments[i] = attachmentInfo[i].view;
773 
774 		renderPassAttachmentBeginInfo =
775 		{
776 			VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO,		// VkStructureType		sType;
777 			DE_NULL,													// const void*			pNext;
778 			(deUint32)attachments.size(),								// deUint32				attachmentCount;
779 			attachments.data()											// const VkImageView*	pAttachments;
780 		};
781 
782 		pNext = &renderPassAttachmentBeginInfo;
783 	}
784 
785 	beginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea,
786 					(deUint32)clearColor.size(), clearColor.data(), VK_SUBPASS_CONTENTS_INLINE, pNext);
787 }
788 
finishRendering(const VkCommandBuffer commandBuffer) const789 void AttachmentRateInstance::finishRendering(const VkCommandBuffer commandBuffer) const
790 {
791 	const DeviceInterface& vk = m_context.getDeviceInterface();
792 
793 	endRenderPass(vk, commandBuffer);
794 }
795 
iterate(void)796 tcu::TestStatus AttachmentRateInstance::iterate(void)
797 {
798 	// instead of creating many classes that derive from large common class
799 	// each test mode is defined in separate run* method, those methods
800 	// then use same helper methods defined in this class
801 
802 	typedef bool (AttachmentRateInstance::*MethodPtr)();
803 	const std::map<TestMode, MethodPtr> modeFuncMap
804 	{
805 		{ TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER,							&AttachmentRateInstance::runComputeShaderMode },
806 		{ TM_SETUP_RATE_WITH_FRAGMENT_SHADER,									&AttachmentRateInstance::runFragmentShaderMode },
807 		{ TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE,							&AttachmentRateInstance::runCopyMode },
808 		{ TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,	&AttachmentRateInstance::runCopyModeOnTransferQueue },
809 		{ TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,	&AttachmentRateInstance::runCopyModeOnTransferQueue },
810 		{ TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE,								&AttachmentRateInstance::runFillLinearTiledImage },
811 		{ TM_TWO_SUBPASS,														&AttachmentRateInstance::runTwoSubpassMode },
812 	};
813 
814 	if ((this->*modeFuncMap.at(m_params->mode))())
815 		return tcu::TestStatus::pass("Pass");
816 
817 	return tcu::TestStatus::fail("Fail");
818 }
819 
verifyUsingAtomicChecks(deUint32 tileWidth,deUint32 tileHeight,deUint32 rateWidth,deUint32 rateHeight,deUint32 * outBufferPtr) const820 bool AttachmentRateInstance::verifyUsingAtomicChecks(deUint32 tileWidth, deUint32 tileHeight,
821 													 deUint32 rateWidth, deUint32 rateHeight,
822 													 deUint32* outBufferPtr) const
823 {
824 	tcu::TestLog&			log					(m_context.getTestContext().getLog());
825 	tcu::TextureLevel		errorMaskStorage	(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_cbWidth, m_cbHeight, 1u);
826 	tcu::PixelBufferAccess	errorMaskAccess		(errorMaskStorage.getAccess());
827 
828 	deUint32		wrongFragments						= 0;
829 	const deUint32	fragmentsWithSameAtomicValueCount	= rateWidth * rateHeight;
830 
831 	// map that uses atomic value as a kay and maps it to all fragments sharing same atomic
832 	std::map<deUint32, std::vector<tcu::UVec2> > fragmentsWithSameAtomicValueMap;
833 
834 	// this method asumes that top and left edge of triangle are parallel to axes
835 	// and we can store just single coordinate for those edges
836 	deUint32 triangleLeftEdgeX	= 0;
837 	deUint32 triangleTopEdgeY	= 0;
838 
839 	// this method assumes that greatest angle in the triangle points to the top-left corner of FB;
840 	// this vector will then store fragments on the right edge of triangle; vector index represents y coordinate and value is x
841 	std::vector<deUint32> fragmentsOnTheRightTriangleEdgeVect(m_cbHeight, 0);
842 
843 	tcu::clear(errorMaskAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0));
844 
845 	// loop over all fragments and validate the output
846 	for (deUint32 cbFragmentY = 0; cbFragmentY < m_cbHeight; ++cbFragmentY)
847 	for (deUint32 cbFragmentX = 0; cbFragmentX < m_cbWidth;  ++cbFragmentX)
848 	{
849 		deUint32* fragmentColor = &outBufferPtr[4 * (cbFragmentY * m_cbWidth + cbFragmentX)];
850 
851 		// fragment not covered by primitive, skip it
852 		if (fragmentColor[2] == 0)
853 			continue;
854 
855 		// first fragment we hit will define top and left triangle edges
856 		if ((triangleTopEdgeY + triangleLeftEdgeX) == 0)
857 		{
858 			triangleLeftEdgeX	= cbFragmentX;
859 			triangleTopEdgeY	= cbFragmentY;
860 		}
861 
862 		// constantly overwrite coordinate on right edge so that we are left with the farthest one
863 		fragmentsOnTheRightTriangleEdgeVect[cbFragmentY] = cbFragmentX;
864 
865 		// make sure that fragment g and a components are 0
866 		if ((fragmentColor[1] != 0) || (fragmentColor[3] != 0))
867 		{
868 			++wrongFragments;
869 			continue;
870 		}
871 
872 		deUint32 rate			= fragmentColor[0];
873 		deUint32 fragmentRateX	= 1 << ((rate / 4) & 3);
874 		deUint32 fragmentRateY	= 1 << (rate & 3);
875 
876 		// check if proper rate was used for fragment
877 		if ((fragmentRateX != rateWidth) ||
878 			(fragmentRateY != rateHeight))
879 		{
880 			++wrongFragments;
881 			errorMaskAccess.setPixel(tcu::Vec4(1.0f, 0.5f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
882 			continue;
883 		}
884 
885 		// mark correct fragments using few green shades so rates are visible
886 		deUint32 atomicValue = fragmentColor[2];
887 		errorMaskAccess.setPixel(tcu::Vec4(0.0f, 1.0f - float(atomicValue % 7) * 0.1f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
888 
889 		// find proper set in map and add value to it after doing verification with existing items
890 		auto fragmentsSetMapIt = fragmentsWithSameAtomicValueMap.find(atomicValue);
891 		if (fragmentsSetMapIt == fragmentsWithSameAtomicValueMap.end())
892 		{
893 			fragmentsWithSameAtomicValueMap[atomicValue] = { tcu::UVec2(cbFragmentX, cbFragmentY) };
894 			fragmentsWithSameAtomicValueMap[atomicValue].reserve(fragmentsWithSameAtomicValueCount);
895 		}
896 		else
897 		{
898 			// make sure that fragments added to set are near the top-left fragment
899 			auto& fragmentsSet = fragmentsSetMapIt->second;
900 			if (((cbFragmentX - fragmentsSet[0].x()) > rateWidth) ||
901 				((cbFragmentY - fragmentsSet[0].y()) > rateHeight))
902 			{
903 				++wrongFragments;
904 				errorMaskAccess.setPixel(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
905 			}
906 
907 			fragmentsWithSameAtomicValueMap[atomicValue].emplace_back(cbFragmentX, cbFragmentY);
908 		}
909 	}
910 
911 	// check if there are no valid fragmenst at all
912 	if ((triangleTopEdgeY + triangleLeftEdgeX) == 0)
913 	{
914 		log << tcu::TestLog::Message
915 			<< "No valid fragments."
916 			<< tcu::TestLog::EndMessage;
917 		return false;
918 	}
919 
920 	// if checks failed skip checking other tile sizes
921 	if (wrongFragments)
922 	{
923 		log << tcu::TestLog::Message
924 			<< "Failed " << wrongFragments << " fragments for tileWidth: " << tileWidth << ", tileHeight: " << tileHeight
925 			<< tcu::TestLog::EndMessage
926 			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMaskAccess);
927 		return false;
928 	}
929 
930 	// do additional checks
931 	tcu::Vec4 fragmentColor(0.0f, 1.0f, 0.0f, 1.0f);
932 
933 	tcu::clear(errorMaskAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0));
934 
935 	// make sure that there is same number of fragments that share same atomic value
936 	for (auto& fragmentsSetMapIt : fragmentsWithSameAtomicValueMap)
937 	{
938 		// mark correct fragments using few green shades so rates are visible
939 		fragmentColor = tcu::Vec4(0.0f, 1.0f - float(fragmentsSetMapIt.first % 7) * 0.1f, 0.0f, 1.0f);
940 
941 		const auto& fragmentSet = fragmentsSetMapIt.second;;
942 		if (fragmentSet.size() != fragmentsWithSameAtomicValueCount)
943 		{
944 			const auto&	topLeftFragment		= fragmentSet[0];
945 			deUint32	triangleRightEdgeX	= fragmentsOnTheRightTriangleEdgeVect[topLeftFragment.y()];
946 
947 			// we can only count this as an error if set is fully inside of triangle, sets on
948 			// edges may not have same number of fragments as sets fully located in the triangle
949 			if ((topLeftFragment.y() > (triangleTopEdgeY)) &&
950 				(topLeftFragment.x() > (triangleLeftEdgeX)) &&
951 				(topLeftFragment.x() < (triangleRightEdgeX - rateWidth)))
952 			{
953 				wrongFragments += (deUint32)fragmentSet.size();
954 				fragmentColor	= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
955 			}
956 		}
957 
958 		// mark all fragmens from set with proper color
959 		for (auto& fragment : fragmentSet)
960 			errorMaskAccess.setPixel(fragmentColor, fragment.x(), fragment.y(), 0u);
961 	}
962 
963 	if (wrongFragments)
964 	{
965 		log << tcu::TestLog::Message
966 			<< "Wrong number of fragments with same atomic value (" << wrongFragments << ") for tileWidth: " << tileWidth << ", tileHeight: " << tileHeight
967 			<< tcu::TestLog::EndMessage
968 			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMaskAccess);
969 		return false;
970 	}
971 
972 	return true;
973 }
974 
runComputeShaderMode(void)975 bool AttachmentRateInstance::runComputeShaderMode(void)
976 {
977 	// clear the shading rate attachment, then using a compute shader, set the shading rate attachment
978 	// values to the desired rate using various atomic operations, then use it to draw a basic triangle
979 	// and do basic checks
980 
981 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
982 	VkDevice				device				= m_context.getDevice();
983 	deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
984 	VkMemoryBarrier			memoryBarrier		{ VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
985 
986 	Move<VkShaderModule>	compShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0);
987 	Move<VkShaderModule>	vertShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
988 	Move<VkShaderModule>	fragShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
989 
990 	Move<VkCommandPool>		cmdPool				= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
991 	Move<VkCommandBuffer>	cmdBuffer			= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
992 
993 	// setup descriptor set with storage image for compute pipeline
994 	Move<VkDescriptorSetLayout>			computeDescriptorSetLayout		= DescriptorSetLayoutBuilder()
995 																			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
996 																			.build(vk, device);
997 	Move<VkDescriptorPool>				computeDescriptorPool			= DescriptorPoolBuilder()
998 																			.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
999 																			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1000 	const VkDescriptorSetAllocateInfo	computeDescriptorSetAllocInfo	= makeDescriptorSetAllocInfo(*computeDescriptorPool, &(*computeDescriptorSetLayout));
1001 	Move<VkDescriptorSet>				computeDescriptorSet			= allocateDescriptorSet(vk, device, &computeDescriptorSetAllocInfo);
1002 
1003 	m_srUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
1004 
1005 	buildCounterBufferObjects();
1006 	buildColorBufferObjects(0, m_cbUsage);
1007 
1008 	// iterate over all possible tile sizes
1009 	for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
1010 	for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1011 	{
1012 		// skip tile sizes that have unsuported aspect ratio
1013 		deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1014 		if (aspectRatio > m_maxAspectRatio)
1015 			continue;
1016 
1017 		// calculate size of shading rate attachment
1018 		deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
1019 		deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1020 
1021 		buildShadingRateObjects(0, srWidth, srHeight, m_srUsage);
1022 
1023 		const VkDescriptorImageInfo  computeDescriptorInfo  = makeDescriptorImageInfo(DE_NULL, *m_srImageView[0], VK_IMAGE_LAYOUT_GENERAL);
1024 		DescriptorSetUpdateBuilder()
1025 			.writeSingle(*computeDescriptorSet,  DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,  &computeDescriptorInfo)
1026 			.update(vk, device);
1027 
1028 		Move<VkPipelineLayout>	computePipelineLayout	= buildPipelineLayout(&(*computeDescriptorSetLayout));
1029 		Move<VkPipelineLayout>	graphicsPipelineLayout	= buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
1030 		Move<VkPipeline>		computePipeline			= buildComputePipeline(*compShader, *computePipelineLayout);
1031 		Move<VkRenderPass>		renderPass				= buildRenderPass(m_cbFormat, tileWidth, tileHeight);
1032 		Move<VkPipeline>		graphicsPipeline		= buildGraphicsPipeline(0, *renderPass, *graphicsPipelineLayout, *vertShader, *fragShader);
1033 
1034 		std::vector<FBAttachmentInfo> attachmentInfo
1035 		{
1036 			{ m_cbFormat,			m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
1037 			{ m_params->srFormat,	m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
1038 		};
1039 		Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
1040 
1041 		beginCommandBuffer(vk, *cmdBuffer, 0u);
1042 
1043 		// wait till sr image layout is changed
1044 		VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1045 		VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
1046 		VkImageMemoryBarrier srImageBarrierGeneral =
1047 			makeImageMemoryBarrier(
1048 				VK_ACCESS_NONE_KHR,
1049 				VK_ACCESS_NONE_KHR,
1050 				VK_IMAGE_LAYOUT_UNDEFINED,
1051 				VK_IMAGE_LAYOUT_GENERAL,
1052 				**m_srImage[0],
1053 				m_defaultImageSubresourceRange);
1054 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierGeneral);
1055 
1056 		// fill sr image using compute shader
1057 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
1058 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0, 1, &(*computeDescriptorSet), 0, DE_NULL);
1059 		vk.cmdDispatch(*cmdBuffer, srWidth, srHeight, 1);
1060 
1061 		// wait till sr image is ready and change sr images layout
1062 		srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
1063 		dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1064 		memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1065 		memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
1066 		VkImageMemoryBarrier srImageBarrierShadingRate =
1067 			makeImageMemoryBarrier(
1068 				VK_ACCESS_SHADER_WRITE_BIT,
1069 				VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1070 				VK_IMAGE_LAYOUT_GENERAL,
1071 				VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
1072 				**m_srImage[0],
1073 				m_defaultImageSubresourceRange);
1074 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 1, &srImageBarrierShadingRate);
1075 
1076 		// wait till cb image layout is changed
1077 		srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1078 		dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1079 		VkImageMemoryBarrier cbImageBarrier =
1080 			makeImageMemoryBarrier(
1081 				VK_ACCESS_NONE_KHR,
1082 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1083 				VK_IMAGE_LAYOUT_UNDEFINED,
1084 				VK_IMAGE_LAYOUT_GENERAL,
1085 				**m_cbImage[0],
1086 				m_defaultImageSubresourceRange);
1087 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
1088 
1089 		startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
1090 
1091 		// draw single triangle to cb
1092 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1093 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1094 		vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1095 
1096 		finishRendering(*cmdBuffer);
1097 
1098 		// wait till color attachment is fully written
1099 		srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1100 		dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1101 		memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1102 		memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1103 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1104 
1105 		// read back color buffer image
1106 		vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
1107 
1108 		endCommandBuffer(vk, *cmdBuffer);
1109 
1110 		// submit commands and wait
1111 		const VkQueue queue = m_context.getUniversalQueue();
1112 		submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1113 
1114 		invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1115 		if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
1116 									 m_params->srRate.width, m_params->srRate.height,
1117 									 (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1118 			return false;
1119 
1120 	}  // iterate over all possible tile sizes
1121 
1122 	return true;
1123 }
1124 
runFragmentShaderMode(void)1125 bool AttachmentRateInstance::runFragmentShaderMode(void)
1126 {
1127 	// Set up the image as a color attachment, and render rate to it,
1128 	// then use it to draw a basic triangle and do basic checks
1129 
1130 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
1131 	VkDevice				device				= m_context.getDevice();
1132 	deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1133 	VkMemoryBarrier			memoryBarrier		{ VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
1134 
1135 	Move<VkShaderModule>	vertSetupShader		= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert_setup"), 0);
1136 	Move<VkShaderModule>	fragSetupShader		= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_setup"), 0);
1137 	Move<VkShaderModule>	vertShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1138 	Move<VkShaderModule>	fragShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1139 
1140 	Move<VkCommandPool>		cmdPool				= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1141 	Move<VkCommandBuffer>	cmdBuffer			= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1142 
1143 	m_srUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1144 
1145 	buildCounterBufferObjects();
1146 	buildColorBufferObjects(0, m_cbUsage);
1147 
1148 	// iterate over all possible tile sizes
1149 	for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
1150 	for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1151 	{
1152 		// skip tile sizes that have unsuported aspect ratio
1153 		deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1154 		if (aspectRatio > m_maxAspectRatio)
1155 			continue;
1156 
1157 		// calculate size of shading rate attachment
1158 		deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
1159 		deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1160 
1161 		buildShadingRateObjects(0, srWidth, srHeight, m_srUsage);
1162 
1163 		Move<VkPipelineLayout>	setupPipelineLayout	= buildPipelineLayout();
1164 		Move<VkPipelineLayout>	ratePipelineLayout	= buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
1165 		Move<VkRenderPass>		setupRenderPass		= buildRenderPass(m_params->srFormat);
1166 		Move<VkRenderPass>		rateRenderPass		= buildRenderPass(m_cbFormat, tileWidth, tileHeight);
1167 		Move<VkPipeline>		setupPipeline		= buildGraphicsPipeline(0, *setupRenderPass, *setupPipelineLayout, *vertSetupShader, *fragSetupShader, DE_FALSE);
1168 		Move<VkPipeline>		ratePipeline		= buildGraphicsPipeline(0, *rateRenderPass, *ratePipelineLayout, *vertShader, *fragShader);
1169 
1170 		std::vector<FBAttachmentInfo> setupAttachmentInfo
1171 		{
1172 			{ m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0] }
1173 		};
1174 		std::vector<FBAttachmentInfo> rateAttachmentInfo
1175 		{
1176 			{ m_cbFormat,			m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
1177 			{ m_params->srFormat,	m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
1178 		};
1179 		Move<VkFramebuffer> setupFramebuffer	= buildFramebuffer(*setupRenderPass, setupAttachmentInfo);
1180 		Move<VkFramebuffer> rateFramebuffer		= buildFramebuffer(*rateRenderPass, rateAttachmentInfo);
1181 
1182 		beginCommandBuffer(vk, *cmdBuffer, 0u);
1183 
1184 		// wait till sr image layout is changed
1185 		VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1186 		VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1187 		VkImageMemoryBarrier srImageBarrierGeneral =
1188 			makeImageMemoryBarrier(
1189 				VK_ACCESS_NONE_KHR,
1190 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1191 				VK_IMAGE_LAYOUT_UNDEFINED,
1192 				VK_IMAGE_LAYOUT_GENERAL,
1193 				**m_srImage[0],
1194 				m_defaultImageSubresourceRange);
1195 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierGeneral);
1196 
1197 		// render rate to sr image
1198 		startRendering(*cmdBuffer, *setupRenderPass, *setupFramebuffer, makeRect2D(srWidth, srHeight), setupAttachmentInfo);
1199 
1200 		// draw single triangle to cb
1201 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *setupPipeline);
1202 		vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1203 
1204 		finishRendering(*cmdBuffer);
1205 
1206 		// wait till sr image is ready and change sr images layout
1207 		srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1208 		dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1209 		VkImageMemoryBarrier srImageBarrierShadingRate =
1210 			makeImageMemoryBarrier(
1211 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1212 				VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1213 				VK_IMAGE_LAYOUT_GENERAL,
1214 				VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
1215 				**m_srImage[0],
1216 				m_defaultImageSubresourceRange);
1217 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierShadingRate);
1218 
1219 		// wait till cb image layout is changed
1220 		srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1221 		dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1222 		VkImageMemoryBarrier cbImageBarrier =
1223 			makeImageMemoryBarrier(
1224 				VK_ACCESS_NONE_KHR,
1225 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1226 				VK_IMAGE_LAYOUT_UNDEFINED,
1227 				VK_IMAGE_LAYOUT_GENERAL,
1228 				**m_cbImage[0],
1229 				m_defaultImageSubresourceRange);
1230 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
1231 
1232 		startRendering(*cmdBuffer, *rateRenderPass, *rateFramebuffer, makeRect2D(m_cbWidth, m_cbHeight), rateAttachmentInfo);
1233 
1234 		// draw single triangle to cb
1235 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *ratePipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1236 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *ratePipeline);
1237 		vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1238 
1239 		finishRendering(*cmdBuffer);
1240 
1241 		// wait till color attachment is fully written
1242 		srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1243 		dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1244 		memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1245 		memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1246 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1247 
1248 		// read back color buffer image
1249 		vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
1250 
1251 		endCommandBuffer(vk, *cmdBuffer);
1252 
1253 		// submit commands and wait
1254 		const VkQueue queue = m_context.getUniversalQueue();
1255 		submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1256 
1257 		invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1258 		if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
1259 									 m_params->srRate.width, m_params->srRate.height,
1260 									 (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1261 			return false;
1262 
1263 	} // iterate over all possible tile sizes
1264 
1265 	return true;
1266 }
1267 
runCopyMode(void)1268 bool AttachmentRateInstance::runCopyMode (void)
1269 {
1270 	// Clear a separate image of the same format to that rate, copy it to
1271 	// the shading rate image, then use it to draw a basic triangle and do basic checks
1272 
1273 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
1274 	VkDevice				device				= m_context.getDevice();
1275 	deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1276 	VkMemoryBarrier			memoryBarrier		{ VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
1277 
1278 	Move<VkShaderModule>	vertShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1279 	Move<VkShaderModule>	fragShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1280 
1281 	Move<VkCommandPool>		cmdPool				= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1282 	Move<VkCommandBuffer>	cmdBuffer			= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1283 
1284 	buildCounterBufferObjects();
1285 	buildColorBufferObjects(0, m_cbUsage);
1286 
1287 	// iterate over all possible tile sizes
1288 	for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
1289 	for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1290 	{
1291 		// skip tile sizes that have unsuported aspect ratio
1292 		deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1293 		if (aspectRatio > m_maxAspectRatio)
1294 			continue;
1295 
1296 		// calculate size of shading rate attachment
1297 		deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
1298 		deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1299 
1300 		buildShadingRateObjects(0, srWidth, srHeight, m_srUsage);
1301 
1302 		// create image that will be source for shading rate image
1303 		de::MovePtr<ImageWithMemory> srSrcImage = buildImageWithMemory(m_params->srFormat, srWidth, srHeight, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1304 
1305 		Move<VkPipelineLayout>	graphicsPipelineLayout	= buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
1306 		Move<VkRenderPass>		renderPass				= buildRenderPass(m_cbFormat, tileWidth, tileHeight);
1307 		Move<VkPipeline>		graphicsPipeline		= buildGraphicsPipeline(0, *renderPass, *graphicsPipelineLayout, *vertShader, *fragShader);
1308 
1309 		std::vector<FBAttachmentInfo> attachmentInfo
1310 		{
1311 			{ m_cbFormat,			m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
1312 			{ m_params->srFormat,	m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
1313 		};
1314 		Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
1315 
1316 		beginCommandBuffer(vk, *cmdBuffer, 0u);
1317 
1318 		// wait till sr images layout are changed
1319 		VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1320 		VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1321 		std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(2,
1322 			makeImageMemoryBarrier(
1323 				VK_ACCESS_NONE_KHR,
1324 				VK_ACCESS_NONE_KHR,
1325 				VK_IMAGE_LAYOUT_UNDEFINED,
1326 				VK_IMAGE_LAYOUT_GENERAL,
1327 				**m_srImage[0],
1328 				m_defaultImageSubresourceRange));
1329 		srImageBarrierGeneral[1].image = **srSrcImage;
1330 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2, srImageBarrierGeneral.data());
1331 
1332 		// clear source sr image with proper rate
1333 		VkClearColorValue clearValue = { { 0, 0, 0, 0 } };
1334 		clearValue.uint32[0] = calculateRate(m_params->srRate.width, m_params->srRate.height);
1335 		vk.cmdClearColorImage(*cmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &m_defaultImageSubresourceRange);
1336 
1337 		// wait till sr source image is ready
1338 		srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1339 		dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1340 		memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1341 		memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1342 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1343 
1344 		// copy sr source image to sr image used during rendering
1345 		VkImageCopy imageCopyRegion
1346 		{
1347 			m_defaultImageSubresourceLayers,	// VkImageSubresourceLayers	srcSubresource;
1348 			{0, 0, 0},							// VkOffset3D				srcOffset;
1349 			m_defaultImageSubresourceLayers,	// VkImageSubresourceLayers	dstSubresource;
1350 			{0, 0, 0},							// VkOffset3D				dstOffset;
1351 			{ srWidth, srHeight, 1u }			// VkExtent3D				extent;
1352 		};
1353 		vk.cmdCopyImage(*cmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL, 1, &imageCopyRegion);
1354 
1355 		// wait till sr image is ready and change sr images layout
1356 		srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1357 		dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1358 		memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1359 		memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
1360 		VkImageMemoryBarrier srImageBarrierShadingRate =
1361 			makeImageMemoryBarrier(
1362 				VK_ACCESS_TRANSFER_WRITE_BIT,
1363 				VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1364 				VK_IMAGE_LAYOUT_GENERAL,
1365 				VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
1366 				**m_srImage[0],
1367 				m_defaultImageSubresourceRange);
1368 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 1, &srImageBarrierShadingRate);
1369 
1370 		// wait till cb image layout is changed
1371 		srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1372 		dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1373 		VkImageMemoryBarrier cbImageBarrier =
1374 			makeImageMemoryBarrier(
1375 				VK_ACCESS_NONE_KHR,
1376 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1377 				VK_IMAGE_LAYOUT_UNDEFINED,
1378 				VK_IMAGE_LAYOUT_GENERAL,
1379 				**m_cbImage[0],
1380 				m_defaultImageSubresourceRange);
1381 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
1382 
1383 		startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
1384 
1385 		// draw single triangle to cb
1386 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1387 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1388 		vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1389 
1390 		finishRendering(*cmdBuffer);
1391 
1392 		// wait till color attachment is fully written
1393 		srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1394 		dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1395 		memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1396 		memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1397 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1398 
1399 		// read back color buffer image
1400 		vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
1401 
1402 		endCommandBuffer(vk, *cmdBuffer);
1403 
1404 		// submit commands and wait
1405 		const VkQueue queue = m_context.getUniversalQueue();
1406 		submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1407 
1408 		invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1409 		if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
1410 									 m_params->srRate.width, m_params->srRate.height,
1411 									 (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1412 			return false;
1413 
1414 	} // iterate over all possible tile sizes
1415 
1416 	return true;
1417 }
1418 
runCopyModeOnTransferQueue(void)1419 bool AttachmentRateInstance::runCopyModeOnTransferQueue(void)
1420 {
1421 	// Clear a separate image of the same format to that rate, copy it to
1422 	// the shading rate image on separate transfer queue and then use copied
1423 	// image to draw a basic triangle and do basic checks
1424 
1425 	const DeviceInterface&					vk							= m_context.getDeviceInterface();
1426 	const PlatformInterface&				vkp							= m_context.getPlatformInterface();
1427 	const InstanceInterface&				vki							= m_context.getInstanceInterface();
1428 	VkPhysicalDevice						pd							= m_context.getPhysicalDevice();
1429 	deUint32								transferQueueFamilyIndex	= std::numeric_limits<deUint32>::max();
1430 	deUint32								graphicsQueueFamilyIndex	= std::numeric_limits<deUint32>::max();
1431 	VkMemoryBarrier							memoryBarrier				{ VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
1432 	std::vector<VkQueueFamilyProperties>	queueFamilyProperties		= getPhysicalDeviceQueueFamilyProperties(vki, pd);
1433 
1434 	// find graphics and transfer queue families
1435 	for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); queueNdx++)
1436 	{
1437 		VkQueueFlags queueFlags = queueFamilyProperties[queueNdx].queueFlags;
1438 		if ((graphicsQueueFamilyIndex == std::numeric_limits<deUint32>::max()) && (queueFlags & VK_QUEUE_GRAPHICS_BIT))
1439 			graphicsQueueFamilyIndex = queueNdx;
1440 		else if ((queueNdx != graphicsQueueFamilyIndex) && (queueFlags & VK_QUEUE_TRANSFER_BIT))
1441 			transferQueueFamilyIndex = queueNdx;
1442 	}
1443 	if (transferQueueFamilyIndex == std::numeric_limits<deUint32>::max())
1444 		TCU_THROW(NotSupportedError, "No separate transfer queue");
1445 
1446 	// using queueFamilies vector to determine if sr image uses exclusiv or concurrent sharing
1447 	std::vector<deUint32> queueFamilies;
1448 	if (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE)
1449 		queueFamilies = { graphicsQueueFamilyIndex, transferQueueFamilyIndex };
1450 
1451 	// create custom device
1452 	{
1453 		const float queuePriorities = 1.0f;
1454 		std::vector<VkDeviceQueueCreateInfo> queueInfo(2,
1455 			{
1456 				VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,		// VkStructureType					sType;
1457 				DE_NULL,										// const void*						pNext;
1458 				(VkDeviceQueueCreateFlags)0u,					// VkDeviceQueueCreateFlags			flags;
1459 				transferQueueFamilyIndex,						// uint32_t							queueFamilyIndex;
1460 				1u,												// uint32_t							queueCount;
1461 				&queuePriorities								// const float*						pQueuePriorities;
1462 			});
1463 		queueInfo[1].queueFamilyIndex = graphicsQueueFamilyIndex;
1464 
1465 		VkPhysicalDeviceFeatures deviceFeatures;
1466 		vki.getPhysicalDeviceFeatures(pd, &deviceFeatures);
1467 
1468 		VkPhysicalDeviceFragmentShadingRateFeaturesKHR	fsrFeatures				{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, DE_NULL, DE_FALSE, DE_FALSE, DE_TRUE };
1469 		VkPhysicalDeviceImagelessFramebufferFeaturesKHR	ifbFeatures				{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, DE_NULL, DE_TRUE };
1470 		VkPhysicalDeviceFeatures2						createPhysicalFeature	{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &fsrFeatures, deviceFeatures };
1471 
1472 		std::vector<const char*> enabledExtensions = { "VK_KHR_fragment_shading_rate" };
1473 		if (m_params->useImagelessFramebuffer)
1474 		{
1475 			enabledExtensions.push_back("VK_KHR_imageless_framebuffer");
1476 			fsrFeatures.pNext = &ifbFeatures;
1477 		}
1478 
1479 		std::vector<const char*> enabledLayers = getValidationLayers(vki, pd);
1480 		VkDeviceCreateInfo deviceInfo
1481 		{
1482 			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,				// VkStructureType					sType;
1483 			&createPhysicalFeature,								// const void*						pNext;
1484 			(VkDeviceCreateFlags)0u,							// VkDeviceCreateFlags				flags;
1485 			2u,													// uint32_t							queueCreateInfoCount;
1486 			queueInfo.data(),									// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
1487 			static_cast<deUint32>(enabledLayers.size()),		// uint32_t							enabledLayerCount;
1488 			de::dataOrNull(enabledLayers),						// const char* const*				ppEnabledLayerNames;
1489 			static_cast<deUint32>(enabledExtensions.size()),	// uint32_t							enabledExtensionCount;
1490 			enabledExtensions.data(),							// const char* const*				ppEnabledExtensionNames;
1491 			DE_NULL												// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
1492 		};
1493 
1494 		m_device		= createDevice(vkp, m_context.getInstance(), vki, pd, &deviceInfo);
1495 		m_allocator		= de::MovePtr<Allocator>(new SimpleAllocator(m_context.getDeviceInterface(), *m_device, getPhysicalDeviceMemoryProperties(vki, pd)));
1496 	}
1497 
1498 	VkQueue transferQueue;
1499 	vk.getDeviceQueue(*m_device, transferQueueFamilyIndex, 0u, &transferQueue);
1500 	VkQueue graphicsQueue;
1501 	vk.getDeviceQueue(*m_device, graphicsQueueFamilyIndex, 0u, &graphicsQueue);
1502 
1503 	// create transfer and graphics command buffers
1504 	Move<VkCommandPool>		transferCmdPool		= createCommandPool(vk, *m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, transferQueueFamilyIndex);
1505 	Move<VkCommandBuffer>	transferCmdBuffer	= allocateCommandBuffer(vk, *m_device, *transferCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1506 	Move<VkCommandPool>		graphicsCmdPool		= createCommandPool(vk, *m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, graphicsQueueFamilyIndex);
1507 	Move<VkCommandBuffer>	graphicsCmdBuffer	= allocateCommandBuffer(vk, *m_device, *graphicsCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1508 
1509 	Move<VkShaderModule>	vertShader			= createShaderModule(vk, *m_device, m_context.getBinaryCollection().get("vert"), 0);
1510 	Move<VkShaderModule>	fragShader			= createShaderModule(vk, *m_device, m_context.getBinaryCollection().get("frag"), 0);
1511 
1512 	buildColorBufferObjects(0, m_cbUsage);
1513 	buildCounterBufferObjects();
1514 
1515 	// iterate over all possible tile sizes
1516 	for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
1517 	for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1518 	{
1519 		// skip tile sizes that have unsuported aspect ratio
1520 		deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1521 		if (aspectRatio > m_maxAspectRatio)
1522 			continue;
1523 
1524 		// calculate size of shading rate attachment
1525 		deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
1526 		deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1527 
1528 		// create image that will be source for shading rate image
1529 		de::MovePtr<ImageWithMemory> srSrcImage = buildImageWithMemory(m_params->srFormat, srWidth, srHeight,
1530 																	   VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1531 
1532 		// create buffer that will contain shading rate source data
1533 		tcu::TextureFormat				srTextureFormat		= mapVkFormat(m_params->srFormat);
1534 		deUint32						srWriteBufferSize	= srWidth * srHeight * getNumUsedChannels(srTextureFormat.order) * getChannelSize(srTextureFormat.type);
1535 		de::MovePtr<BufferWithMemory>	srSrcBuffer			= buildBufferWithMemory(srWriteBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1536 
1537 		// fill buffer with tested shading rate
1538 		deUint8*	srWriteBufferHostPtr	= (deUint8*)srSrcBuffer->getAllocation().getHostPtr();
1539 		deUint8		value					= (deUint8)calculateRate(m_params->srRate.width, m_params->srRate.height);
1540 		deMemset(srWriteBufferHostPtr, value, (size_t)srWriteBufferSize);
1541 		flushAlloc(vk, *m_device, srSrcBuffer->getAllocation());
1542 
1543 		// create shading rate iamge
1544 		m_srImage[0]		= buildImageWithMemory(m_params->srFormat, srWidth, srHeight,
1545 												   VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1546 												   VK_IMAGE_TILING_OPTIMAL, queueFamilies);
1547 		m_srImageView[0]	= buildImageView(m_params->srFormat, m_srImage[0]->get());
1548 
1549 		Move<VkPipelineLayout>	graphicsPipelineLayout	= buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
1550 		Move<VkRenderPass>		renderPass				= buildRenderPass(m_cbFormat, tileWidth, tileHeight);
1551 		Move<VkPipeline>		graphicsPipeline		= buildGraphicsPipeline(0, *renderPass, *graphicsPipelineLayout, *vertShader, *fragShader);
1552 
1553 		std::vector<FBAttachmentInfo> attachmentInfo
1554 		{
1555 			{ m_cbFormat,			m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
1556 			{ m_params->srFormat,	m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
1557 		};
1558 		Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
1559 
1560 		beginCommandBuffer(vk, *transferCmdBuffer, 0u);
1561 
1562 		// wait till sr data is ready in buffer and change sr image layouts to general
1563 		VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1564 		VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1565 		memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1566 		memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1567 		std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(2,
1568 			makeImageMemoryBarrier(
1569 				VK_ACCESS_NONE_KHR,
1570 				VK_ACCESS_NONE_KHR,
1571 				VK_IMAGE_LAYOUT_UNDEFINED,
1572 				VK_IMAGE_LAYOUT_GENERAL,
1573 				**m_srImage[0],
1574 				m_defaultImageSubresourceRange));
1575 		srImageBarrierGeneral[1].image = **srSrcImage;
1576 		vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 2, srImageBarrierGeneral.data());
1577 
1578 		// copy sr data to images
1579 		const VkBufferImageCopy srCopyBuffer = makeBufferImageCopy({ srWidth, srHeight, 1u }, m_defaultImageSubresourceLayers);
1580 		vk.cmdCopyBufferToImage(*transferCmdBuffer, **srSrcBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, 1, &srCopyBuffer);
1581 
1582 		// wait till sr source image is ready
1583 		srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1584 		dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1585 		memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1586 		memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1587 		vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1588 
1589 		// copy sr source image to sr image used during rendering
1590 		VkImageCopy imageCopyRegion
1591 		{
1592 			m_defaultImageSubresourceLayers,	// VkImageSubresourceLayers	srcSubresource;
1593 			{0, 0, 0},							// VkOffset3D				srcOffset;
1594 			m_defaultImageSubresourceLayers,	// VkImageSubresourceLayers	dstSubresource;
1595 			{0, 0, 0},							// VkOffset3D				dstOffset;
1596 			{ srWidth, srHeight, 1u }			// VkExtent3D				extent;
1597 		};
1598 		vk.cmdCopyImage(*transferCmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL, 1, &imageCopyRegion);
1599 
1600 		// release exclusive ownership from the transfer queue family
1601 		srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1602 		dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1603 		VkImageMemoryBarrier srImageBarrierOwnershipTransfer =
1604 			makeImageMemoryBarrier(
1605 				VK_ACCESS_TRANSFER_WRITE_BIT,
1606 				VK_ACCESS_NONE_KHR,
1607 				VK_IMAGE_LAYOUT_GENERAL,
1608 				VK_IMAGE_LAYOUT_GENERAL,
1609 				**m_srImage[0], m_defaultImageSubresourceRange);
1610 		if (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE)
1611 		{
1612 			srImageBarrierOwnershipTransfer.srcQueueFamilyIndex = transferQueueFamilyIndex;
1613 			srImageBarrierOwnershipTransfer.dstQueueFamilyIndex = graphicsQueueFamilyIndex;
1614 		}
1615 		vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierOwnershipTransfer);
1616 
1617 		endCommandBuffer(vk, *transferCmdBuffer);
1618 
1619 		beginCommandBuffer(vk, *graphicsCmdBuffer, 0u);
1620 
1621 		// acquire exclusive ownership for the graphics queue family - while changing sr images layout
1622 		vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierOwnershipTransfer);
1623 
1624 		// wait till sr image layout is changed
1625 		srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1626 		dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1627 		VkImageMemoryBarrier srImageBarrierShadingRate =
1628 			makeImageMemoryBarrier(
1629 				VK_ACCESS_NONE_KHR,
1630 				VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1631 				VK_IMAGE_LAYOUT_GENERAL,
1632 				VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
1633 				**m_srImage[0],
1634 				m_defaultImageSubresourceRange);
1635 		vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierShadingRate);
1636 
1637 		// wait till cb image layout is changed
1638 		srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1639 		dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1640 		VkImageMemoryBarrier cbImageBarrier =
1641 			makeImageMemoryBarrier(
1642 				VK_ACCESS_NONE_KHR,
1643 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1644 				VK_IMAGE_LAYOUT_UNDEFINED,
1645 				VK_IMAGE_LAYOUT_GENERAL,
1646 				**m_cbImage[0],
1647 				m_defaultImageSubresourceRange);
1648 		vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
1649 
1650 		startRendering(*graphicsCmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
1651 
1652 		// draw single triangle to cb
1653 		vk.cmdBindDescriptorSets(*graphicsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1654 		vk.cmdBindPipeline(*graphicsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1655 		vk.cmdDraw(*graphicsCmdBuffer, 3u, 1, 0u, 0u);
1656 
1657 		finishRendering(*graphicsCmdBuffer);
1658 
1659 		// wait till color attachment is fully written
1660 		srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1661 		dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1662 		memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1663 		memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1664 		vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1665 
1666 		// read back color buffer image
1667 		vk.cmdCopyImageToBuffer(*graphicsCmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
1668 
1669 		endCommandBuffer(vk, *graphicsCmdBuffer);
1670 
1671 		// create synchronization objects
1672 		Move<VkSemaphore>	semaphore		= createSemaphore(vk, *m_device);
1673 		Move<VkFence>		transferFence	= createFence(vk, *m_device);
1674 		Move<VkFence>		graphicsFence	= createFence(vk, *m_device);
1675 
1676 		const VkSubmitInfo transferSubmitInfo
1677 		{
1678 			VK_STRUCTURE_TYPE_SUBMIT_INFO,						// VkStructureType				sType;
1679 			DE_NULL,											// const void*					pNext;
1680 			0u,													// deUint32						waitSemaphoreCount;
1681 			DE_NULL,											// const VkSemaphore*			pWaitSemaphores;
1682 			DE_NULL,											// const VkPipelineStageFlags*	pWaitDstStageMask;
1683 			1u,													// deUint32						commandBufferCount;
1684 			&*transferCmdBuffer,								// const VkCommandBuffer*		pCommandBuffers;
1685 			1u,													// deUint32						signalSemaphoreCount;
1686 			&*semaphore,										// const VkSemaphore*			pSignalSemaphores;
1687 		};
1688 		const VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
1689 		const VkSubmitInfo graphicsSubmitInfo
1690 		{
1691 			VK_STRUCTURE_TYPE_SUBMIT_INFO,						// VkStructureType				sType;
1692 			DE_NULL,											// const void*					pNext;
1693 			1u,													// deUint32						waitSemaphoreCount;
1694 			&*semaphore,										// const VkSemaphore*			pWaitSemaphores;
1695 			&waitDstStageMask,									// const VkPipelineStageFlags*	pWaitDstStageMask;
1696 			1u,													// deUint32						commandBufferCount;
1697 			&*graphicsCmdBuffer,								// const VkCommandBuffer*		pCommandBuffers;
1698 			0u,													// deUint32						signalSemaphoreCount;
1699 			DE_NULL,											// const VkSemaphore*			pSignalSemaphores;
1700 		};
1701 
1702 		// submit commands to both queues
1703 		VK_CHECK(vk.queueSubmit(transferQueue, 1u, &transferSubmitInfo, *transferFence));
1704 		VK_CHECK(vk.queueSubmit(graphicsQueue, 1u, &graphicsSubmitInfo, *graphicsFence));
1705 
1706 		VkFence fences[] = { *graphicsFence, *transferFence };
1707 		VK_CHECK(vk.waitForFences(*m_device, 2u, fences, DE_TRUE, ~0ull));
1708 
1709 		invalidateAlloc(vk, *m_device, m_cbReadBuffer[0]->getAllocation());
1710 		if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
1711 									 m_params->srRate.width, m_params->srRate.height,
1712 									 (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1713 			return false;
1714 
1715 	} // iterate over all possible tile sizes
1716 
1717 	return true;
1718 }
1719 
runFillLinearTiledImage(void)1720 bool AttachmentRateInstance::runFillLinearTiledImage(void)
1721 {
1722 	// Create a linear tiled fragment shading rate attachment image and set
1723 	// its data on the host, then draw a basic triangle and do basic checks
1724 
1725 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
1726 	VkDevice				device				= m_context.getDevice();
1727 	deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1728 	VkImageSubresource		imageSubresource	= makeImageSubresource(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u);
1729 	VkMemoryBarrier			memoryBarrier		{ VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
1730 	VkSubresourceLayout		srImageLayout;
1731 
1732 	Move<VkShaderModule>	vertShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1733 	Move<VkShaderModule>	fragShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1734 
1735 	Move<VkCommandPool>		cmdPool				= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1736 	Move<VkCommandBuffer>	cmdBuffer			= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1737 
1738 	buildCounterBufferObjects();
1739 	buildColorBufferObjects(0, m_cbUsage);
1740 
1741 	// iterate over all possible tile sizes
1742 	for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
1743 	for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1744 	{
1745 		// skip tile sizes that have unsuported aspect ratio
1746 		deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1747 		if (aspectRatio > m_maxAspectRatio)
1748 			continue;
1749 
1750 		// calculate size of shading rate attachment
1751 		deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
1752 		deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1753 
1754 		buildShadingRateObjects(0, srWidth, srHeight, m_srUsage, VK_IMAGE_TILING_LINEAR);
1755 
1756 		deUint8*	imagePtr	= reinterpret_cast<deUint8*>(m_srImage[0]->getAllocation().getHostPtr());
1757 		deUint8		value		= (deUint8)calculateRate(m_params->srRate.width, m_params->srRate.height);
1758 
1759 		// fill sr image on the host row by row
1760 		vk.getImageSubresourceLayout(device, **m_srImage[0], &imageSubresource, &srImageLayout);
1761 		for (deUint32 srTexelRow = 0; srTexelRow < srHeight; srTexelRow++)
1762 		{
1763 			deUint8* rowDst = imagePtr + srImageLayout.offset + srImageLayout.rowPitch * srTexelRow;
1764 			deMemset(rowDst, value, (size_t)srWidth);
1765 		}
1766 
1767 		Move<VkPipelineLayout>	graphicsPipelineLayout	= buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
1768 		Move<VkRenderPass>		renderPass				= buildRenderPass(m_cbFormat, tileWidth, tileHeight);
1769 		Move<VkPipeline>		graphicsPipeline		= buildGraphicsPipeline(0, *renderPass, *graphicsPipelineLayout, *vertShader, *fragShader);
1770 
1771 		std::vector<FBAttachmentInfo> attachmentInfo
1772 		{
1773 			{ m_cbFormat,			m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
1774 			{ m_params->srFormat,	m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
1775 		};
1776 		Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
1777 
1778 		beginCommandBuffer(vk, *cmdBuffer, 0u);
1779 
1780 		// wait till sr image layout is changed
1781 		VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1782 		VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1783 		VkImageMemoryBarrier srImageBarrierAttachment =
1784 			makeImageMemoryBarrier(
1785 				VK_ACCESS_NONE_KHR,
1786 				VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1787 				VK_IMAGE_LAYOUT_UNDEFINED,
1788 				VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
1789 				**m_srImage[0],
1790 				m_defaultImageSubresourceRange);
1791 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierAttachment);
1792 
1793 		// wait till cb image layout is changed
1794 		srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1795 		dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1796 		VkImageMemoryBarrier cbImageBarrier =
1797 			makeImageMemoryBarrier(
1798 				VK_ACCESS_NONE_KHR,
1799 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1800 				VK_IMAGE_LAYOUT_UNDEFINED,
1801 				VK_IMAGE_LAYOUT_GENERAL,
1802 				**m_cbImage[0],
1803 				m_defaultImageSubresourceRange);
1804 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
1805 
1806 		startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
1807 
1808 		// draw single triangle to cb
1809 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1810 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1811 		vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1812 
1813 		finishRendering(*cmdBuffer);
1814 
1815 		// wait till color attachment is fully written
1816 		srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1817 		dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1818 		memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1819 		memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1820 		vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1821 
1822 		// read back color buffer image
1823 		vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
1824 
1825 		endCommandBuffer(vk, *cmdBuffer);
1826 
1827 		// submit commands and wait
1828 		const VkQueue queue = m_context.getUniversalQueue();
1829 		submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1830 
1831 		invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1832 		if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
1833 									 m_params->srRate.width, m_params->srRate.height,
1834 									 (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1835 			return false;
1836 
1837 	} // iterate over all possible tile sizes
1838 
1839 	return true;
1840 }
1841 
runTwoSubpassMode(void)1842 bool AttachmentRateInstance::runTwoSubpassMode(void)
1843 {
1844 	// Set up a two-subpass render pass with different shading rate attachments used in each subpass.
1845 	// Then draw a basic triangle in each subpass and do basic checks.
1846 
1847 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
1848 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1849 	VkPhysicalDevice			pd					= m_context.getPhysicalDevice();
1850 	VkDevice					device				= m_context.getDevice();
1851 	deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1852 	VkMemoryBarrier				memoryBarrier		{ VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
1853 
1854 	Move<VkShaderModule>		vertShader0			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert0"), 0);
1855 	Move<VkShaderModule>		vertShader1			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert1"), 0);
1856 	Move<VkShaderModule>		fragShader			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1857 
1858 	Move<VkCommandPool>			cmdPool				= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1859 	Move<VkCommandBuffer>		cmdBuffer			= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1860 
1861 	// fetch information about supported rates
1862 	deUint32 supportedFragmentShadingRateCount;
1863 	std::vector<VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates;
1864 	vki.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, DE_NULL);
1865 	supportedFragmentShadingRates.resize(supportedFragmentShadingRateCount, {
1866 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,				// VkStructureType		sType;
1867 		DE_NULL,																	// void*				pNext;
1868 		VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlags	sampleCounts;
1869 		{ 0, 0 }																	// VkExtent2D			fragmentSize;
1870 		});
1871 	vki.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, &supportedFragmentShadingRates[0]);
1872 
1873 	// grab min and max tile sieze and biggest and smallest rate
1874 	deUint32 sr0Width		= (m_cbWidth + m_minTileSize.width - 1) / m_minTileSize.width;
1875 	deUint32 sr0Height		= (m_cbHeight + m_minTileSize.height - 1) / m_minTileSize.height;
1876 	deUint32 sr1Width		= (m_cbWidth + m_maxTileSize.width - 1) / m_maxTileSize.width;
1877 	deUint32 sr1Height		= (m_cbHeight + m_maxTileSize.height - 1) / m_maxTileSize.height;
1878 	deUint32 sr0RateWidth	= supportedFragmentShadingRates[0].fragmentSize.width;										// bigets supported rate
1879 	deUint32 sr0RateHeight	= supportedFragmentShadingRates[0].fragmentSize.height;
1880 	deUint32 sr1RateWidth	= supportedFragmentShadingRates[supportedFragmentShadingRateCount - 2].fragmentSize.width;	// smallest supported rate excluding {1, 1}
1881 	deUint32 sr1RateHeight	= supportedFragmentShadingRates[supportedFragmentShadingRateCount - 2].fragmentSize.height;
1882 
1883 	buildColorBufferObjects(0, m_cbUsage);
1884 	buildColorBufferObjects(1, m_cbUsage);
1885 	buildShadingRateObjects(0, sr0Width, sr0Height, m_srUsage);
1886 	buildShadingRateObjects(1, sr1Width, sr1Height, m_srUsage);
1887 	buildCounterBufferObjects();
1888 
1889 	Move<VkRenderPass>		renderPass			= buildRenderPass(m_cbFormat, m_minTileSize.width, m_minTileSize.height, m_maxTileSize.width, m_maxTileSize.height);
1890 	Move<VkPipelineLayout>	pipelineLayout		= buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
1891 	Move<VkPipeline>		graphicsPipeline0	= buildGraphicsPipeline(0, *renderPass, *pipelineLayout, *vertShader0, *fragShader);
1892 	Move<VkPipeline>		graphicsPipeline1	= buildGraphicsPipeline(1, *renderPass, *pipelineLayout, *vertShader1, *fragShader);
1893 
1894 	std::vector<FBAttachmentInfo> attachmentInfo
1895 	{
1896 		{ m_cbFormat,			m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
1897 		{ m_params->srFormat,	m_srUsage, sr0Width,  sr0Height,  *m_srImageView[0] },
1898 		{ m_cbFormat,			m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[1] },
1899 		{ m_params->srFormat,	m_srUsage, sr1Width,  sr1Height,  *m_srImageView[1] }
1900 	};
1901 	Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
1902 
1903 	beginCommandBuffer(vk, *cmdBuffer, 0u);
1904 
1905 	// change sr image layouts to general
1906 	VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1907 	VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1908 	std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(2,
1909 		makeImageMemoryBarrier(
1910 			VK_ACCESS_NONE_KHR,
1911 			VK_ACCESS_NONE_KHR,
1912 			VK_IMAGE_LAYOUT_UNDEFINED,
1913 			VK_IMAGE_LAYOUT_GENERAL,
1914 			**m_srImage[0],
1915 			m_defaultImageSubresourceRange));
1916 	srImageBarrierGeneral[1].image = **m_srImage[1];
1917 	vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2, srImageBarrierGeneral.data());
1918 
1919 	VkClearColorValue clearValues[2] = { { { 0, 0, 0, 0 } }, { { 0, 0, 0, 0 } } };
1920 	clearValues[0].uint32[0] = calculateRate(sr0RateWidth, sr0RateHeight);
1921 	clearValues[1].uint32[0] = calculateRate(sr1RateWidth, sr1RateHeight);
1922 	vk.cmdClearColorImage(*cmdBuffer, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL, &clearValues[0], 1, &m_defaultImageSubresourceRange);
1923 	vk.cmdClearColorImage(*cmdBuffer, **m_srImage[1], VK_IMAGE_LAYOUT_GENERAL, &clearValues[1], 1, &m_defaultImageSubresourceRange);
1924 
1925 	// wait till sr data is ready and change sr images layout
1926 	srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1927 	dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1928 	memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1929 	memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
1930 	std::vector<VkImageMemoryBarrier> srImageBarrierShadingRate(2,
1931 		makeImageMemoryBarrier(
1932 			VK_ACCESS_TRANSFER_WRITE_BIT,
1933 			VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1934 			VK_IMAGE_LAYOUT_GENERAL,
1935 			VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
1936 			**m_srImage[0],
1937 			m_defaultImageSubresourceRange));
1938 	srImageBarrierShadingRate[1].image = **m_srImage[1];
1939 	vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 2, srImageBarrierShadingRate.data());
1940 
1941 	// wait till cb image layouts are changed
1942 	srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1943 	dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1944 	std::vector<VkImageMemoryBarrier> cbImageBarrier(2,
1945 		makeImageMemoryBarrier(
1946 			VK_ACCESS_NONE_KHR,
1947 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1948 			VK_IMAGE_LAYOUT_UNDEFINED,
1949 			VK_IMAGE_LAYOUT_GENERAL,
1950 			**m_cbImage[0],
1951 			m_defaultImageSubresourceRange));
1952 	cbImageBarrier[1].image = **m_cbImage[1];
1953 	vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2, cbImageBarrier.data());
1954 
1955 	startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
1956 
1957 	// draw single triangle to first cb
1958 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1959 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline0);
1960 	vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1961 
1962 	vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1963 
1964 	// draw single triangle to second cb
1965 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline1);
1966 	vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1967 
1968 	finishRendering(*cmdBuffer);
1969 
1970 	// wait till color attachments are fully written
1971 	srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1972 	dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1973 	memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1974 	memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1975 	vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1976 
1977 	// read back color buffer images
1978 	vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
1979 	vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[1], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[1], 1u, &m_defaultBufferImageCopy);
1980 
1981 	endCommandBuffer(vk, *cmdBuffer);
1982 
1983 	// submit commands and wait
1984 	const VkQueue queue = m_context.getUniversalQueue();
1985 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1986 
1987 	// read back buffer with color attachment 1 data
1988 	Allocation& cb0BuffAlloc = m_cbReadBuffer[0]->getAllocation();
1989 	invalidateAlloc(vk, device, cb0BuffAlloc);
1990 
1991 	// read back buffer with color attachment 2 data
1992 	Allocation& cb1BuffAlloc = m_cbReadBuffer[1]->getAllocation();
1993 	invalidateAlloc(vk, device, cb1BuffAlloc);
1994 
1995 	// validate both attachemtns triangle
1996 	return (verifyUsingAtomicChecks(m_minTileSize.width, m_minTileSize.height,
1997 									sr0RateWidth, sr0RateHeight,
1998 									(deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()) &&
1999 			verifyUsingAtomicChecks(m_maxTileSize.width, m_maxTileSize.height,
2000 									sr1RateWidth, sr1RateHeight,
2001 									(deUint32*)m_cbReadBuffer[1]->getAllocation().getHostPtr()));
2002 }
2003 
2004 class AttachmentRateTestCase : public TestCase
2005 {
2006 public:
2007 					AttachmentRateTestCase	(tcu::TestContext& context, const char* name, de::SharedPtr<TestParams> params);
2008 					~AttachmentRateTestCase	(void) = default;
2009 
2010 	void			initPrograms			(SourceCollections& programCollection) const override;
2011 	TestInstance*	createInstance			(Context& context) const override;
2012 	void			checkSupport			(Context& context) const override;
2013 
2014 private:
2015 
2016 	const de::SharedPtr<TestParams> m_params;
2017 };
2018 
AttachmentRateTestCase(tcu::TestContext & context,const char * name,de::SharedPtr<TestParams> params)2019 AttachmentRateTestCase::AttachmentRateTestCase(tcu::TestContext& context, const char* name, de::SharedPtr<TestParams> params)
2020 	: vkt::TestCase	(context, name, "")
2021 	, m_params		(params)
2022 {
2023 }
2024 
checkSupport(Context & context) const2025 void AttachmentRateTestCase::checkSupport(Context& context) const
2026 {
2027 	context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
2028 	if (m_params->useImagelessFramebuffer)
2029 		context.requireDeviceFunctionality("VK_KHR_imageless_framebuffer");
2030 
2031 	if (!context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
2032 		TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
2033 
2034 	const vk::InstanceInterface&	vk					= context.getInstanceInterface();
2035 	const vk::VkPhysicalDevice		pd					= context.getPhysicalDevice();
2036 
2037 	VkImageFormatProperties			imageProperties;
2038 	VkImageUsageFlags				srUsage				= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
2039 														  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2040 
2041 	VkResult result = vk.getPhysicalDeviceImageFormatProperties(pd, m_params->srFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, srUsage, 0, &imageProperties);
2042 	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
2043 		TCU_THROW(NotSupportedError, "Format not supported");
2044 
2045 	if (m_params->mode != TM_TWO_SUBPASS)
2046 	{
2047 		deUint32												supportedFragmentShadingRateCount;
2048 		VkExtent2D												testedRate = m_params->srRate;
2049 		std::vector<VkPhysicalDeviceFragmentShadingRateKHR>		supportedFragmentShadingRates;
2050 
2051 		// fetch information about supported rates
2052 		vk.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, DE_NULL);
2053 		supportedFragmentShadingRates.resize(supportedFragmentShadingRateCount, {
2054 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,				// VkStructureType		sType;
2055 			DE_NULL,																	// void*				pNext;
2056 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlags	sampleCounts;
2057 			{ 0, 0 }																	// VkExtent2D			fragmentSize;
2058 			});
2059 		vk.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, &supportedFragmentShadingRates[0]);
2060 
2061 		// check if rate required by test is not supported
2062 		if (std::none_of(supportedFragmentShadingRates.begin(), supportedFragmentShadingRates.end(),
2063 			[&testedRate](const VkPhysicalDeviceFragmentShadingRateKHR& r)
2064 			{ return (r.fragmentSize.width == testedRate.width && r.fragmentSize.height == testedRate.height); }))
2065 		{
2066 			TCU_THROW(NotSupportedError, "Rate not supported");
2067 		}
2068 	}
2069 
2070 	VkFormatFeatureFlags requiredFeatures = 0;
2071 	if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2072 		requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
2073 	else if ((m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE) ||
2074 			 (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE) ||
2075 			 (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE) ||
2076 			 (m_params->mode == TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE))
2077 		requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2078 	else if (m_params->mode == TM_SETUP_RATE_WITH_FRAGMENT_SHADER)
2079 		requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
2080 
2081 #if DEBUG_USE_STORE_INSTEAD_OF_ATOMICS == 1
2082 	if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2083 		requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
2084 #endif
2085 
2086 	if (requiredFeatures)
2087 	{
2088 		const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vk, pd, m_params->srFormat);
2089 
2090 		if (m_params->mode == TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE)
2091 		{
2092 			if ((formatProperties.linearTilingFeatures & requiredFeatures) != requiredFeatures)
2093 				TCU_THROW(NotSupportedError, "Required format feature bits not supported");
2094 		}
2095 		else if ((formatProperties.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
2096 			TCU_THROW(NotSupportedError, "Required format feature bits not supported");
2097 	}
2098 }
2099 
initPrograms(SourceCollections & programCollection) const2100 void AttachmentRateTestCase::initPrograms(SourceCollections& programCollection) const
2101 {
2102 	deUint32 rateValue = calculateRate(m_params->srRate.width, m_params->srRate.height);
2103 
2104 	if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2105 	{
2106 		std::stringstream compStream;
2107 		compStream <<
2108 			"#version 450\n"
2109 			"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2110 			"layout(r32ui, binding = 0) coherent uniform highp uimage2D srImage;\n"
2111 			"void main (void)\n"
2112 			"{\n"
2113 #if DEBUG_USE_STORE_INSTEAD_OF_ATOMICS == 1
2114 			"  imageStore(srImage, ivec2(gl_GlobalInvocationID.xy), uvec4(" << rateValue << "));\n"
2115 #else
2116 			"  imageAtomicAdd(srImage, ivec2(gl_GlobalInvocationID.xy), " << rateValue << ");\n"
2117 #endif
2118 			"}\n";
2119 
2120 		programCollection.glslSources.add("comp") << glu::ComputeSource(compStream.str());
2121 	}
2122 
2123 	tcu::StringTemplate vertTemplate(
2124 		"#version 450 core\n"
2125 		"out gl_PerVertex\n"
2126 		"{\n"
2127 		"  vec4 gl_Position;\n"
2128 		"};\n"
2129 		"void main()\n"
2130 		"{\n"
2131 		"  gl_Position = vec4(float(1.0 - 2.0 * int(gl_VertexIndex != 1)) * ${SCALE} + ${TRANSLATE},\n"
2132 		"                     float(1.0 - 2.0 * int(gl_VertexIndex > 0))  * ${SCALE} + ${TRANSLATE}, 0.0, 1.0);\n"
2133 		"}\n");
2134 
2135 	std::map<std::string, std::string> specializationMap
2136 	{
2137 		{"SCALE",		"0.8" },
2138 		{"TRANSLATE",	"0.0" },
2139 	};
2140 
2141 	if (m_params->mode == TM_TWO_SUBPASS)
2142 	{
2143 		specializationMap["SCALE"]		=  "0.4";
2144 		specializationMap["TRANSLATE"]	= "-0.5";
2145 		programCollection.glslSources.add("vert0") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2146 
2147 		specializationMap["SCALE"]		= "0.4";
2148 		specializationMap["TRANSLATE"]	= "0.5";
2149 		programCollection.glslSources.add("vert1") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2150 	}
2151 	else
2152 	{
2153 		programCollection.glslSources.add("vert") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2154 	}
2155 
2156 	if (m_params->mode == TM_SETUP_RATE_WITH_FRAGMENT_SHADER)
2157 	{
2158 		// use large triangle that will cover whole color buffer
2159 		specializationMap["SCALE"]		= "9.0";
2160 		specializationMap["TRANSLATE"]	= "0.0";
2161 		programCollection.glslSources.add("vert_setup") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2162 
2163 		std::stringstream fragStream;
2164 		fragStream <<
2165 			"#version 450 core\n"
2166 			"layout(location = 0) out uint outColor;\n"
2167 			"void main()\n"
2168 			"{\n"
2169 			"  outColor.x = " << rateValue << ";\n"
2170 			"}\n";
2171 		programCollection.glslSources.add("frag_setup") << glu::FragmentSource(fragStream.str());
2172 	}
2173 
2174 	std::string frag =
2175 		"#version 450 core\n"
2176 		"#extension GL_EXT_fragment_shading_rate : enable\n"
2177 		"layout(set = 0, binding = 0) buffer Block { uint counter; } buf;\n"
2178 		"layout(location = 0) out uvec4 outColor;\n"
2179 		"void main()\n"
2180 		"{\n"
2181 		"  outColor.x = gl_ShadingRateEXT;\n"
2182 		"  outColor.y = 0;\n"
2183 		"  outColor.z = atomicAdd(buf.counter, 1);\n"
2184 		"  outColor.w = 0;\n"
2185 		"}\n";
2186 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
2187 }
2188 
createInstance(Context & context) const2189 TestInstance* AttachmentRateTestCase::createInstance(Context& context) const
2190 {
2191 	return new AttachmentRateInstance(context, m_params);
2192 }
2193 
2194 }	// anonymous
2195 
createAttachmentRateTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)2196 void createAttachmentRateTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
2197 {
2198 	struct SRFormat
2199 	{
2200 		VkFormat		format;
2201 		const char*		name;
2202 	};
2203 
2204 	const std::vector<SRFormat> srFormats
2205 	{
2206 		{ VK_FORMAT_R8_UINT,				"r8_uint" },
2207 		{ VK_FORMAT_R8G8_UINT,				"r8g8_uint" },
2208 		{ VK_FORMAT_R8G8B8_UINT,			"r8g8b8_uint" },
2209 		{ VK_FORMAT_R8G8B8A8_UINT,			"r8g8b8a8_uint" },
2210 		{ VK_FORMAT_R16_UINT,				"r16_uint" },
2211 		{ VK_FORMAT_R16G16_UINT,			"r16g16_uint" },
2212 		{ VK_FORMAT_R16G16B16_UINT,			"r16g16b16_uint" },
2213 		{ VK_FORMAT_R16G16B16A16_UINT,		"r16g16b16a16_uint" },
2214 		{ VK_FORMAT_R32_UINT,				"r32_uint" },
2215 		{ VK_FORMAT_R32G32_UINT,			"r32g32_uint" },
2216 		{ VK_FORMAT_R32G32B32_UINT,			"r32g32b32_uint" },
2217 		{ VK_FORMAT_R32G32B32A32_UINT,		"r32g32b32a32_uint" },
2218 		{ VK_FORMAT_R64_UINT,				"r64_uint" },
2219 		{ VK_FORMAT_R64G64_UINT,			"r64g64_uint" },
2220 		{ VK_FORMAT_R64G64B64_UINT,			"r64g64b64_uint" },
2221 		{ VK_FORMAT_R64G64B64A64_UINT,		"r64g64b64a64_uint" },
2222 	};
2223 
2224 	struct SRRate
2225 	{
2226 		VkExtent2D		count;
2227 		const char*		name;
2228 	};
2229 
2230 	const std::vector<SRRate> srRates
2231 	{
2232 		{ {1, 1},	"rate_1x1" },
2233 		{ {1, 2},	"rate_1x2" },
2234 		{ {1, 4},	"rate_1x4" },
2235 		{ {2, 1},	"rate_2x1" },
2236 		{ {2, 2},	"rate_2x2" },
2237 		{ {2, 4},	"rate_2x4" },
2238 		{ {4, 1},	"rate_4x1" },
2239 		{ {4, 2},	"rate_4x2" },
2240 		{ {4, 4},	"rate_4x4" },
2241 	};
2242 
2243 	struct TestModeParam
2244 	{
2245 		TestMode		mode;
2246 		const char*		name;
2247 	};
2248 
2249 	const std::vector<TestModeParam> testModeParams
2250 	{
2251 		{ TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER,							"setup_with_atomics" },
2252 		{ TM_SETUP_RATE_WITH_FRAGMENT_SHADER,									"setup_with_fragment" },
2253 		{ TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE,							"setup_with_copying" },
2254 		{ TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,	"setup_with_copying_using_transfer_queue_concurent" },
2255 		{ TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,	"setup_with_copying_using_transfer_queue_exclusive" },
2256 		{ TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE,								"setup_with_linear_tiled_image" },
2257 	};
2258 
2259 	de::MovePtr<tcu::TestCaseGroup> mainGroup(new tcu::TestCaseGroup(testCtx, "attachment_rate", ""));
2260 
2261 	for (const auto& testModeParam : testModeParams)
2262 	{
2263 		de::MovePtr<tcu::TestCaseGroup> testModeGroup(new tcu::TestCaseGroup(testCtx, testModeParam.name, ""));
2264 
2265 		for (const auto& srFormat : srFormats)
2266 		{
2267 			de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, srFormat.name, ""));
2268 			for (const auto& srRate : srRates)
2269 			{
2270 				formatGroup->addChild(new AttachmentRateTestCase(testCtx, srRate.name, de::SharedPtr<TestParams>(
2271 					new TestParams
2272 					{
2273 						testModeParam.mode,						// TestMode			mode;
2274 						srFormat.format,						// VkFormat			srFormat;
2275 						srRate.count,							// VkExtent2D		srRate;
2276 						false									// bool				useImagelessFramebuffer;
2277 					}
2278 				)));
2279 
2280 				// duplicate all tests for imageless framebuffer
2281 				std::string imagelessName = std::string(srRate.name) + "_imageless";
2282 				formatGroup->addChild(new AttachmentRateTestCase(testCtx, imagelessName.c_str(), de::SharedPtr<TestParams>(
2283 					new TestParams
2284 					{
2285 						testModeParam.mode,						// TestMode			mode;
2286 						srFormat.format,						// VkFormat			srFormat;
2287 						srRate.count,							// VkExtent2D		srRate;
2288 						true									// bool				useImagelessFramebuffer;
2289 					}
2290 				)));
2291 			}
2292 
2293 			testModeGroup->addChild(formatGroup.release());
2294 		}
2295 
2296 		mainGroup->addChild(testModeGroup.release());
2297 	}
2298 
2299 	de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc", ""));
2300 	miscGroup->addChild(new AttachmentRateTestCase(testCtx, "two_subpass", de::SharedPtr<TestParams>(
2301 		new TestParams
2302 		{
2303 			TM_TWO_SUBPASS,										// TestMode			mode;
2304 			VK_FORMAT_R8_UINT,									// VkFormat			srFormat;
2305 			{0, 0},												// VkExtent2D		srRate;						// not used in TM_TWO_SUBPASS
2306 			false												// bool				useImagelessFramebuffer;
2307 		}
2308 	)));
2309 	mainGroup->addChild(miscGroup.release());
2310 
2311 	parentGroup->addChild(mainGroup.release());
2312 }
2313 
2314 }	// FragmentShadingRage
2315 }	// vkt
2316