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