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