• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 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  vktGlobalPriorityQueueTests.cpp
21  * \brief Global Priority Queue Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktGlobalPriorityQueueTests.hpp"
25 #include "vktGlobalPriorityQueueUtils.hpp"
26 
27 #include "vkBarrierUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkBuilderUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "../image/vktImageTestsUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkStrUtil.hpp"
36 #include "vkRefUtil.hpp"
37 
38 #include "vktTestGroupUtil.hpp"
39 #include "vktTestCase.hpp"
40 
41 #include "deDefs.h"
42 #include "deMath.h"
43 #include "deRandom.h"
44 #include "deRandom.hpp"
45 #include "deSharedPtr.hpp"
46 #include "deString.h"
47 #include "deMemory.h"
48 
49 #include "tcuStringTemplate.hpp"
50 
51 #include <string>
52 #include <sstream>
53 #include <map>
54 
55 using namespace vk;
56 
57 namespace vkt
58 {
59 namespace synchronization
60 {
61 namespace
62 {
63 
64 enum class SyncType
65 {
66 	None,
67 	Semaphore
68 };
69 
70 struct TestConfig
71 {
72 	VkQueueFlagBits				transitionFrom;
73 	VkQueueFlagBits				transitionTo;
74 	VkQueueGlobalPriorityKHR	priorityFrom;
75 	VkQueueGlobalPriorityKHR	priorityTo;
76 	bool						enableProtected;
77 	bool						enableSparseBinding;
78 	SyncType					syncType;
79 	deUint32					width;
80 	deUint32					height;
81 	VkFormat					format;
82 	bool selectFormat (const InstanceInterface& vk, VkPhysicalDevice dev, std::initializer_list<VkFormat> formats);
83 };
84 
selectFormat(const InstanceInterface & vk,VkPhysicalDevice dev,std::initializer_list<VkFormat> formats)85 bool TestConfig::selectFormat (const InstanceInterface& vk, VkPhysicalDevice dev, std::initializer_list<VkFormat> formats)
86 {
87 	auto doesFormatMatch = [](const VkFormat fmt) -> bool
88 	{
89 		const auto tcuFmt = mapVkFormat(fmt);
90 		return tcuFmt.order == tcu::TextureFormat::ChannelOrder::R;
91 	};
92 	VkFormatProperties2 props{};
93 	const VkFormatFeatureFlags flags = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
94 										| VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
95 	for (auto i = formats.begin(); i != formats.end(); ++i)
96 	{
97 		props.sType				= VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
98 		props.pNext				= nullptr;
99 		props.formatProperties	= {};
100 		const VkFormat		fmt = *i;
101 		vk.getPhysicalDeviceFormatProperties2(dev, fmt, &props);
102 		if (doesFormatMatch(fmt) && ((props.formatProperties.optimalTilingFeatures & flags) == flags))
103 		{
104 			this->format = fmt;
105 			return true;
106 		}
107 	}
108 	return false;
109 }
110 
111 struct CheckerboardBuilder
112 {
CheckerboardBuildervkt::synchronization::__anon66461ea50111::CheckerboardBuilder113 	CheckerboardBuilder (uint32_t width, uint32_t height)
114 		: m_width(width), m_height(height) {}
115 
blackFieldCountvkt::synchronization::__anon66461ea50111::CheckerboardBuilder116 	static uint32_t blackFieldCount (uint32_t w, uint32_t h)
117 	{
118 		return ((w+1)/2)*((h+1)/2)+(w/2)*(h/2);
119 	}
120 
blackFieldCountvkt::synchronization::__anon66461ea50111::CheckerboardBuilder121 	uint32_t blackFieldCount () const
122 	{
123 		return blackFieldCount(m_width, m_height);
124 	}
125 
fieldIndexvkt::synchronization::__anon66461ea50111::CheckerboardBuilder126 	uint32_t fieldIndex (uint32_t x, uint32_t y) const
127 	{
128 		return blackFieldCount(m_width, y) + (x / 2);
129 	}
130 
buildVerticesAndIndicesvkt::synchronization::__anon66461ea50111::CheckerboardBuilder131 	void buildVerticesAndIndices (std::vector<float>& vertices, std::vector<uint32_t>& indices) const
132 	{
133 		const uint32_t	vertPerQuad		= 4;
134 		const uint32_t	indexPerQuad	= 6;
135 		const uint32_t	quadCount		= blackFieldCount();
136 		const uint32_t	compPerQuad		= vertPerQuad * 2;
137 		const uint32_t	vertCount		= quadCount * vertPerQuad;
138 		const uint32_t	indexCount		= quadCount * indexPerQuad;
139 
140 		vertices.resize(vertCount * 2);
141 		indices.resize(indexCount);
142 
143 		for (uint32_t z = 0; z < 2; ++z)
144 		for (uint32_t y = 0; y < m_height; ++y)
145 		for (uint32_t x = 0; x < m_width; ++x)
146 		{
147 			if (((x + y) % 2) == 1)
148 				continue;
149 
150 			const float x1 = float(x) / float(m_width);
151 			const float y1 = float(y) / float(m_height);
152 			const float x2 = (float(x) + 1.0f) / float(m_width);
153 			const float y2 = (float(y) + 1.0f) / float(m_height);
154 
155 			const float xx1 = x1 * 2.0f - 1.0f;
156 			const float yy1 = y1 * 2.0f - 1.0f;
157 			const float xx2 = x2 * 2.0f - 1.0f;
158 			const float yy2 = y2 * 2.0f - 1.0f;
159 
160 			const uint32_t quad = fieldIndex(x, y);
161 
162 			if (z == 0)
163 			{
164 				vertices[ quad * compPerQuad  + 0 ] = xx1;
165 				vertices[ quad * compPerQuad  + 1 ] = yy1;
166 				vertices[ quad * compPerQuad  + 2 ] = xx2;
167 				vertices[ quad * compPerQuad  + 3 ] = yy1;
168 
169 				indices[ quad * indexPerQuad + 0 ] = quad * vertPerQuad + 0;
170 				indices[ quad * indexPerQuad + 1 ] = quad * vertPerQuad + 1;
171 				indices[ quad * indexPerQuad + 2 ] = quad * vertPerQuad + 2;
172 			}
173 			else
174 			{
175 				vertices[ quad * compPerQuad  + 4 ] = xx2;
176 				vertices[ quad * compPerQuad  + 5 ] = yy2;
177 				vertices[ quad * compPerQuad  + 6 ] = xx1;
178 				vertices[ quad * compPerQuad  + 7 ] = yy2;
179 
180 				indices[ quad * indexPerQuad + 3 ] = quad * vertPerQuad + 2;
181 				indices[ quad * indexPerQuad + 4 ] = quad * vertPerQuad + 3;
182 				indices[ quad * indexPerQuad + 5 ] = quad * vertPerQuad + 0;
183 			}
184 		}
185 	}
186 
187 private:
188 	uint32_t	m_width;
189 	uint32_t	m_height;
190 };
191 
192 template<class T, class P = T(*)[1]>
begin(void * p)193 auto begin (void* p) -> decltype(std::begin(*std::declval<P>()))
194 {
195 	return std::begin(*static_cast<P>(p));
196 }
197 
198 class GPQInstanceBase : public TestInstance
199 {
200 public:
201 	typedef std::initializer_list<VkDescriptorSetLayout> DSLayouts;
202 	typedef tcu::ConstPixelBufferAccess	BufferAccess;
203 
204 					GPQInstanceBase			(Context&					ctx,
205 											 const TestConfig&			cfg);
206 	template<class PushConstant = void>
207 		auto		createPipelineLayout	(DSLayouts					setLayouts)		const -> Move<VkPipelineLayout>;
208 	auto			createGraphicsPipeline	(VkPipelineLayout			pipelineLayout,
209 											 VkRenderPass				renderPass)			  -> Move<VkPipeline>;
210 	auto			createComputePipeline	(VkPipelineLayout			pipelineLayout)		  -> Move<VkPipeline>;
211 	auto			createImage				(VkImageUsageFlags			usage,
212 											 deUint32					queueFamilyIdx,
213 											 VkQueue					queue)			const -> de::MovePtr<ImageWithMemory>;
214 	auto			createView				(VkImage					image,
215 											 VkImageSubresourceRange&	range)			const -> Move<VkImageView>;
216 	void			submitCommands			(VkCommandBuffer			producerCmd,
217 											 VkCommandBuffer			consumerCmd)	const;
218 	bool			verify					(const BufferAccess&		result,
219 											 deUint32					blackColor,
220 											 deUint32					whiteColor)		const;
221 protected:
222 	auto createPipelineLayout			(const VkPushConstantRange*		pRange,
223 										 DSLayouts						setLayouts)		const -> Move<VkPipelineLayout>;
224 	const TestConfig		m_config;
225 	const SpecialDevice		m_device;
226 	Move<VkShaderModule>	m_vertex;
227 	Move<VkShaderModule>	m_fragment;
228 	Move<VkShaderModule>	m_compute;
229 };
GPQInstanceBase(Context & ctx,const TestConfig & cfg)230 GPQInstanceBase::GPQInstanceBase (Context& ctx, const TestConfig& cfg)
231 	: TestInstance	(ctx)
232 	, m_config		(cfg)
233 	, m_device		(ctx,
234 					 cfg.transitionFrom,	cfg.transitionTo,
235 					 cfg.priorityFrom,		cfg.priorityTo,
236 					 cfg.enableProtected,	cfg.enableSparseBinding)
237 	, m_vertex		()
238 	, m_fragment	()
239 	, m_compute		()
240 {
241 }
242 
createImage(VkImageUsageFlags usage,deUint32 queueFamilyIdx,VkQueue queue) const243 de::MovePtr<ImageWithMemory> GPQInstanceBase::createImage (VkImageUsageFlags usage, deUint32 queueFamilyIdx, VkQueue queue) const
244 {
245 	const InstanceInterface&	vki		= m_context.getInstanceInterface();
246 	const DeviceInterface&		vkd		= m_context.getDeviceInterface();
247 	const VkPhysicalDevice		phys	= m_context.getPhysicalDevice();
248 	const VkDevice				dev		= m_device.device;
249 	Allocator&					alloc	= m_device.getAllocator();
250 	VkImageCreateFlags			flags	= 0;
251 
252 	if (m_config.enableProtected)		flags |= VK_IMAGE_CREATE_PROTECTED_BIT;
253 	if (m_config.enableSparseBinding)	flags |= (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT);
254 
255 	VkImageCreateInfo imageInfo{};
256 	imageInfo.sType					= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
257 	imageInfo.pNext					= nullptr;
258 	imageInfo.flags					= flags;
259 	imageInfo.imageType				= VK_IMAGE_TYPE_2D;
260 	imageInfo.format				= m_config.format;
261 	imageInfo.extent.width			= m_config.width;
262 	imageInfo.extent.height			= m_config.height;
263 	imageInfo.extent.depth			= 1;
264 	imageInfo.mipLevels				= 1;
265 	imageInfo.arrayLayers			= 1;
266 	imageInfo.samples				= VK_SAMPLE_COUNT_1_BIT;
267 	imageInfo.tiling				= VK_IMAGE_TILING_OPTIMAL;
268 	imageInfo.usage					= usage;
269 	imageInfo.sharingMode			= VK_SHARING_MODE_EXCLUSIVE;
270 	imageInfo.queueFamilyIndexCount	= 1;
271 	imageInfo.pQueueFamilyIndices	= &queueFamilyIdx;
272 	imageInfo.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
273 
274 	return de::MovePtr<ImageWithMemory>(new ImageWithMemory(vki, vkd, phys, dev, alloc, imageInfo, queue));
275 }
276 
createView(VkImage image,VkImageSubresourceRange & range) const277 Move<VkImageView> GPQInstanceBase::createView	(VkImage image, VkImageSubresourceRange& range) const
278 {
279 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
280 	const VkDevice			dev		= m_device.device;
281 
282 	range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
283 	return makeImageView(vkd, dev, image, VK_IMAGE_VIEW_TYPE_2D, m_config.format, range);
284 }
285 
createPipelineLayout(const VkPushConstantRange * pRange,DSLayouts setLayouts) const286 Move<VkPipelineLayout>	GPQInstanceBase::createPipelineLayout (const VkPushConstantRange* pRange, DSLayouts setLayouts) const
287 {
288 	std::vector<VkDescriptorSetLayout>	layouts(setLayouts.size());
289 	auto ii = setLayouts.begin();
290 	for (auto i = ii; i != setLayouts.end(); ++i)
291 		layouts[std::distance(ii, i)] = *i;
292 
293 	VkPipelineLayoutCreateInfo		info{};
294 	info.sType					= VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
295 	info.pNext					= nullptr;
296 	info.flags					= VkPipelineLayoutCreateFlags(0);
297 	info.setLayoutCount			= static_cast<uint32_t>(layouts.size());
298 	info.pSetLayouts			= layouts.size() ? layouts.data() : nullptr;
299 	info.pushConstantRangeCount	= pRange ? 1 : 0;
300 	info.pPushConstantRanges	= pRange;
301 
302 	return ::vk::createPipelineLayout(m_context.getDeviceInterface(), m_device.device, &info);
303 }
304 
createPipelineLayout(DSLayouts setLayouts) const305 template<> Move<VkPipelineLayout> DE_UNUSED_FUNCTION GPQInstanceBase::createPipelineLayout<void> (DSLayouts setLayouts) const
306 {
307 	return createPipelineLayout(nullptr, setLayouts);
308 }
309 
createPipelineLayout(DSLayouts setLayouts) const310 template<class PushConstant> Move<VkPipelineLayout>	GPQInstanceBase::createPipelineLayout (DSLayouts setLayouts) const
311 {
312 	VkPushConstantRange	range{};
313 	range.stageFlags	= VK_SHADER_STAGE_ALL;
314 	range.offset		= 0;
315 	range.size			= static_cast<uint32_t>(sizeof(PushConstant));
316 	return createPipelineLayout(&range, setLayouts);
317 }
318 
createGraphicsPipeline(VkPipelineLayout pipelineLayout,VkRenderPass renderPass)319 Move<VkPipeline> GPQInstanceBase::createGraphicsPipeline (VkPipelineLayout pipelineLayout, VkRenderPass renderPass)
320 {
321 	const DeviceInterface&	vkd	= m_context.getDeviceInterface();
322 	const VkDevice			dev	= m_device.device;
323 
324 	m_vertex	= createShaderModule(vkd, dev, m_context.getBinaryCollection().get("vert"));
325 	m_fragment	= createShaderModule(vkd, dev, m_context.getBinaryCollection().get("frag"));
326 
327 	const std::vector<VkViewport>	viewports		{ makeViewport(m_config.width, m_config.height) };
328 	const std::vector<VkRect2D>		scissors		{ makeRect2D(m_config.width, m_config.height) };
329 	const auto						vertexBinding	= makeVertexInputBindingDescription(0u, static_cast<deUint32>(2 * sizeof(float)), VK_VERTEX_INPUT_RATE_VERTEX);
330 	const auto						vertexAttrib	= makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32_SFLOAT, 0u);
331 	const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo
332 	{
333 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
334 		nullptr,														//	const void*									pNext;
335 		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
336 		1u,																//	deUint32									vertexBindingDescriptionCount;
337 		&vertexBinding,													//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
338 		1u,																//	deUint32									vertexAttributeDescriptionCount;
339 		&vertexAttrib													//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
340 	};
341 
342 	return makeGraphicsPipeline(vkd, dev, pipelineLayout,*m_vertex,VkShaderModule(0),
343 						 VkShaderModule(0),VkShaderModule(0),*m_fragment,renderPass,viewports, scissors,
344 						 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,0,0,&vertexInputStateCreateInfo);
345 
346 
347 }
348 
createComputePipeline(VkPipelineLayout pipelineLayout)349 Move<VkPipeline> GPQInstanceBase::createComputePipeline	(VkPipelineLayout	pipelineLayout)
350 {
351 	const DeviceInterface&	vk	= m_context.getDeviceInterface();
352 	const VkDevice			dev	= m_device.device;
353 
354 	m_compute = createShaderModule(vk, dev, m_context.getBinaryCollection().get("comp"));
355 
356 	VkPipelineShaderStageCreateInfo	sci{};
357 	sci.sType				= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
358 	sci.pNext				= nullptr;
359 	sci.flags				= VkPipelineShaderStageCreateFlags(0);
360 	sci.stage				= VK_SHADER_STAGE_COMPUTE_BIT;
361 	sci.module				= *m_compute;
362 	sci.pName				= "main";
363 	sci.pSpecializationInfo	= nullptr;
364 
365 	VkComputePipelineCreateInfo	ci{};
366 	ci.sType				= VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
367 	ci.pNext				= nullptr;
368 	ci.flags				= VkPipelineCreateFlags(0);
369 	ci.stage				= sci;
370 	ci.layout				= pipelineLayout;
371 	ci.basePipelineHandle	= VkPipeline(0);
372 	ci.basePipelineIndex	= 0;
373 
374 	return vk::createComputePipeline(vk, dev, VkPipelineCache(0), &ci, nullptr);
375 }
376 
377 VkPipelineStageFlags queueFlagBitToPipelineStage (VkQueueFlagBits bit);
submitCommands(VkCommandBuffer producerCmd,VkCommandBuffer consumerCmd) const378 void GPQInstanceBase::submitCommands (VkCommandBuffer producerCmd, VkCommandBuffer consumerCmd) const
379 {
380 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
381 	const VkDevice			dev		= m_device.device;
382 
383 	Move<VkSemaphore>		sem		= createSemaphore(vkd, dev);
384 	Move<VkFence>			fence	= createFence(vkd, dev);
385 
386 	const VkSubmitInfo		semSubmitProducer
387 	{
388 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
389 		nullptr,						// const void*					pNext;
390 		0,								// deUint32						waitSemaphoreCount;
391 		nullptr,						// const VkSemaphore*			pWaitSemaphores;
392 		nullptr,						// const VkPipelineStageFlags*	pWaitDstStageMask;
393 		1u,								// deUint32						commandBufferCount;
394 		&producerCmd,					// const VkCommandBuffer*		pCommandBuffers;
395 		1u,								// deUint32						signalSemaphoreCount;
396 		&sem.get(),						// const VkSemaphore*			pSignalSemaphores;
397 	};
398 
399 	const VkPipelineStageFlags	dstWaitStages = VK_PIPELINE_STAGE_TRANSFER_BIT |
400 											    queueFlagBitToPipelineStage(m_config.transitionTo);
401 	const VkSubmitInfo		semSubmitConsumer
402 	{
403 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
404 		nullptr,						// const void*					pNext;
405 		1u,								// deUint32						waitSemaphoreCount;
406 		&(*sem),						// const VkSemaphore*			pWaitSemaphores;
407 		&dstWaitStages,					// const VkPipelineStageFlags*	pWaitDstStageMask;
408 		1u,								// deUint32						commandBufferCount;
409 		&consumerCmd,					// const VkCommandBuffer*		pCommandBuffers;
410 		0,								// deUint32						signalSemaphoreCount;
411 		nullptr,						// const VkSemaphore*			pSignalSemaphores;
412 	};
413 
414 	switch (m_config.syncType)
415 	{
416 	case SyncType::None:
417 		submitCommandsAndWait(vkd, dev, m_device.queueFrom, producerCmd);
418 		submitCommandsAndWait(vkd, dev, m_device.queueTo, consumerCmd);
419 		break;
420 	case SyncType::Semaphore:
421 		VK_CHECK(vkd.queueSubmit(m_device.queueFrom, 1u, &semSubmitProducer, VkFence(0)));
422 		VK_CHECK(vkd.queueSubmit(m_device.queueTo, 1u, &semSubmitConsumer, *fence));
423 		VK_CHECK(vkd.waitForFences(dev, 1u, &fence.get(), DE_TRUE, ~0ull));
424 		break;
425 	}
426 }
427 
428 template<VkQueueFlagBits, VkQueueFlagBits> class GPQInstance;
429 #define DECLARE_INSTANCE(flagsFrom_, flagsTo_)									\
430 	template<> class GPQInstance<flagsFrom_, flagsTo_> : public GPQInstanceBase	\
431 	{	public:	GPQInstance (Context& ctx, const TestConfig& cfg)				\
432 					: GPQInstanceBase(ctx, cfg)	{ }								\
433 				virtual tcu::TestStatus	iterate (void) override;				}
434 
435 DECLARE_INSTANCE(VK_QUEUE_GRAPHICS_BIT,	VK_QUEUE_COMPUTE_BIT);
436 DECLARE_INSTANCE(VK_QUEUE_COMPUTE_BIT,	VK_QUEUE_GRAPHICS_BIT);
437 
438 class GPQCase;
439 typedef TestInstance* (GPQCase::* CreateInstanceProc)(Context&) const;
440 typedef std::pair<VkQueueFlagBits,VkQueueFlagBits> CreateInstanceKey;
441 typedef std::map<CreateInstanceKey, CreateInstanceProc> CreateInstanceMap;
442 #define MAPENTRY(from_,to_) m_createInstanceMap[{from_,to_}] = &GPQCase::createInstance<from_,to_>
443 
444 class GPQCase : public TestCase
445 {
446 public:
447 					GPQCase				(tcu::TestContext&	ctx,
448 										 const std::string&	name,
449 										 const TestConfig&	cfg,
450 										 const std::string&	desc = {});
451 	void			initPrograms		(SourceCollections&	programs)	const override;
452 	TestInstance*	createInstance		(Context&			context)	const override;
453 	void			checkSupport		(Context&			context)	const override;
454 	static deUint32	testValue;
455 
456 private:
457 	template<VkQueueFlagBits, VkQueueFlagBits>
458 		TestInstance*	createInstance	(Context&			context)	const;
459 	mutable TestConfig	m_config;
460 	CreateInstanceMap	m_createInstanceMap;
461 };
462 deUint32 GPQCase::testValue = 113;
463 
GPQCase(tcu::TestContext & ctx,const std::string & name,const TestConfig & cfg,const std::string & desc)464 GPQCase::GPQCase (tcu::TestContext&		ctx,
465 				  const std::string&	name,
466 				  const TestConfig&		cfg,
467 				  const std::string&	desc)
468 	: TestCase				(ctx, name, desc)
469 	, m_config				(cfg)
470 	, m_createInstanceMap	()
471 {
472 	MAPENTRY(VK_QUEUE_GRAPHICS_BIT,	VK_QUEUE_COMPUTE_BIT);
473 	MAPENTRY(VK_QUEUE_COMPUTE_BIT,	VK_QUEUE_GRAPHICS_BIT);
474 }
475 
queueFlagBitToPipelineStage(VkQueueFlagBits bit)476 VkPipelineStageFlags queueFlagBitToPipelineStage (VkQueueFlagBits bit)
477 {
478 	switch (bit) {
479 	case VK_QUEUE_COMPUTE_BIT:
480 		return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
481 	case VK_QUEUE_GRAPHICS_BIT:
482 		return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
483 	default:
484 		DE_ASSERT(VK_FALSE);
485 	}
486 	return VK_QUEUE_FLAG_BITS_MAX_ENUM;
487 }
488 
489 template<VkQueueFlagBits flagsFrom, VkQueueFlagBits flagsTo>
createInstance(Context & context) const490 TestInstance* GPQCase::createInstance (Context& context) const
491 {
492 	return new GPQInstance<flagsFrom, flagsTo>(context, m_config);
493 }
494 
createInstance(Context & context) const495 TestInstance* GPQCase::createInstance (Context& context) const
496 {
497 	const CreateInstanceKey	key(m_config.transitionFrom, m_config.transitionTo);
498 	return (this->*(m_createInstanceMap.at(key)))(context);
499 }
500 
operator <<(std::ostream & str,const VkQueueFlagBits & bit)501 std::ostream& operator<<(std::ostream& str, const VkQueueFlagBits& bit)
502 {
503 	const char* s = nullptr;
504 	const auto d = std::to_string(bit);
505 	switch (bit)
506 	{
507 		case VK_QUEUE_GRAPHICS_BIT:			s = "VK_QUEUE_GRAPHICS_BIT";		break;
508 		case VK_QUEUE_COMPUTE_BIT:			s = "VK_QUEUE_COMPUTE_BIT";			break;
509 		case VK_QUEUE_TRANSFER_BIT:			s = "VK_QUEUE_TRANSFER_BIT";		break;
510 		case VK_QUEUE_SPARSE_BINDING_BIT:	s = "VK_QUEUE_SPARSE_BINDING_BIT";	break;
511 		case VK_QUEUE_PROTECTED_BIT:		s = "VK_QUEUE_PROTECTED_BIT";		break;
512 		default:							s = d.c_str();						break;
513 	}
514 	return (str << s);
515 }
516 
checkSupport(Context & context) const517 void GPQCase::checkSupport (Context& context) const
518 {
519 	const InstanceInterface&	vki = context.getInstanceInterface();
520 	const VkPhysicalDevice		dev = context.getPhysicalDevice();
521 
522 	context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
523 	context.requireDeviceFunctionality("VK_EXT_global_priority");
524 
525 	if (!m_config.selectFormat(vki, dev, { VK_FORMAT_R32_SINT, VK_FORMAT_R32_UINT, VK_FORMAT_R8_SINT, VK_FORMAT_R8_UINT }))
526 	{
527 		TCU_THROW(NotSupportedError, "Unable to find a proper format");
528 	}
529 
530 	VkPhysicalDeviceProtectedMemoryFeatures	memFeatures
531 	{
532 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
533 		nullptr,
534 		VK_FALSE
535 	};
536 	VkPhysicalDeviceFeatures2	devFeatures
537 	{
538 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
539 		&memFeatures,
540 		{}
541 	};
542 	vki.getPhysicalDeviceFeatures2(dev, &devFeatures);
543 
544 	if (m_config.enableProtected && (VK_FALSE == memFeatures.protectedMemory))
545 	{
546 		TCU_THROW(NotSupportedError, "Queue families with VK_QUEUE_PROTECTED_BIT not supported");
547 	}
548 
549 	const VkBool32 sparseEnabled = devFeatures.features.sparseBinding & devFeatures.features.sparseResidencyBuffer & devFeatures.features.sparseResidencyImage2D;
550 	if (m_config.enableSparseBinding && (VK_FALSE == sparseEnabled))
551 	{
552 		TCU_THROW(NotSupportedError, "Queue families with VK_QUEUE_SPARSE_BINDING_BIT not supported");
553 	}
554 
555 	auto assertUnavailableQueue = [](const deUint32 qIdx, VkQueueFlagBits qfb, VkQueueGlobalPriorityKHR qgp)
556 	{
557 		if (qIdx == INVALID_UINT32) {
558 			std::ostringstream buf;
559 			buf << "Unable to create a queue " << qfb << " with a priority " << qgp;
560 			buf.flush();
561 			TCU_THROW(NotSupportedError, buf.str());
562 		}
563 	};
564 
565 	const bool priorityQueryEnabled = context.isDeviceFunctionalitySupported("VK_EXT_global_priority_query");
566 
567 	VkQueueFlags	flagFrom	= m_config.transitionFrom;
568 	VkQueueFlags	flagTo		= m_config.transitionTo;
569 	if (m_config.enableProtected)
570 	{
571 		flagFrom |= VK_QUEUE_PROTECTED_BIT;
572 		flagTo	|= VK_QUEUE_PROTECTED_BIT;
573 	}
574 	if (m_config.enableSparseBinding)
575 	{
576 		flagFrom |= VK_QUEUE_SPARSE_BINDING_BIT;
577 		flagTo	|= VK_QUEUE_SPARSE_BINDING_BIT;
578 	}
579 
580 	const deUint32 queueFromIndex	= findQueueFamilyIndex(vki, dev, flagFrom,
581 														   SpecialDevice::getColissionFlags(m_config.transitionFrom),
582 														   priorityQueryEnabled,
583 														   QueueGlobalPriorities({m_config.priorityFrom}));
584 	assertUnavailableQueue(queueFromIndex, m_config.transitionFrom, m_config.priorityFrom);
585 
586 	const deUint32 queueToIndex		= findQueueFamilyIndex(vki, dev, flagTo,
587 														   SpecialDevice::getColissionFlags(m_config.transitionTo),
588 														   priorityQueryEnabled,
589 														   QueueGlobalPriorities({m_config.priorityTo}));
590 	assertUnavailableQueue(queueToIndex, m_config.transitionTo, m_config.priorityTo);
591 
592 	if (queueFromIndex == queueToIndex)
593 	{
594 		std::ostringstream buf;
595 		buf << "Unable to find separate queues " << m_config.transitionFrom << " and " << m_config.transitionTo;
596 		buf.flush();
597 		TCU_THROW(NotSupportedError, buf.str());
598 	}
599 }
600 
getShaderImageBufferType(const tcu::TextureFormat & format)601 std::string getShaderImageBufferType (const tcu::TextureFormat& format)
602 {
603 	return image::getFormatPrefix(format) + "imageBuffer";
604 }
605 
initPrograms(SourceCollections & programs) const606 void GPQCase::initPrograms (SourceCollections& programs) const
607 {
608 	const std::string producerComp(R"glsl(
609 	#version 450
610 	layout(std430, push_constant) uniform PC
611 		{ uint width, height; } pc;
612 	struct Index { uint k; };
613 	struct Quad { vec2 c[4]; };
614 	layout(set=0, binding=0) buffer Quads
615 		{ Quad data[]; } quads;
616 	layout(set=0, binding=1) buffer Indices
617 		{ Index data[]; } indices;
618 	uint fieldCount (uint w, uint h) {
619 		return ((w+1)/2)*((h+1)/2)+(w/2)*(h/2);
620 	}
621 	uint fieldIndex () {
622 		return	fieldCount(pc.width, gl_GlobalInvocationID.y) + (gl_GlobalInvocationID.x / 2);
623 	}
624 	void main() {
625 		float x1 = float(gl_GlobalInvocationID.x) / float(pc.width);
626 		float y1 = float(gl_GlobalInvocationID.y) / float(pc.height);
627 		float x2 = (float(gl_GlobalInvocationID.x) + 1.0) / float(pc.width);
628 		float y2 = (float(gl_GlobalInvocationID.y) + 1.0) / float(pc.height);
629 
630 		float xx1 = x1 * 2.0 - 1.0;
631 		float yy1 = y1 * 2.0 - 1.0;
632 		float xx2 = x2 * 2.0 - 1.0;
633 		float yy2 = y2 * 2.0 - 1.0;
634 
635 		if (((gl_GlobalInvocationID.x + gl_GlobalInvocationID.y) % 2) == 0)
636 		{
637 			uint at = fieldIndex();
638 
639 			if (gl_GlobalInvocationID.z == 0)
640 			{
641 				quads.data[at].c[0] = vec2(xx1, yy1);
642 				quads.data[at].c[1] = vec2(xx2, yy1);
643 				indices.data[at*6+0].k = at * 4 + 0;
644 				indices.data[at*6+1].k = at * 4 + 1;
645 				indices.data[at*6+2].k = at * 4 + 2;
646 			}
647 			else
648 			{
649 				quads.data[at].c[2] = vec2(xx2, yy2);
650 				quads.data[at].c[3] = vec2(xx1, yy2);
651 				indices.data[at*6+3].k = at * 4 + 2;
652 				indices.data[at*6+4].k = at * 4 + 3;
653 				indices.data[at*6+5].k = at * 4 + 0;
654 			}
655 		}
656 	}
657 	)glsl");
658 
659 	const tcu::StringTemplate consumerComp(R"glsl(
660 	#version 450
661 	layout(std430, push_constant) uniform PC
662 		{ uint width, height; } pc;
663 	struct Pixel { uint k; };
664 	layout(${IMAGE_FORMAT}, set=0, binding=0) readonly uniform ${IMAGE_TYPE} srcImage;
665 	layout(binding=1) writeonly coherent buffer Pixels { Pixel data[]; } pixels;
666 	void main()
667 	{
668 		ivec2 pos2 = ivec2(gl_GlobalInvocationID.xy);
669 		int   pos1 = int(gl_GlobalInvocationID.y * pc.width + gl_GlobalInvocationID.x);
670 		pixels.data[pos1].k = uint(imageLoad(srcImage, pos2).r) + 1;
671 	}
672 	)glsl");
673 
674 	const std::string vert(R"glsl(
675 	#version 450
676 	layout(location = 0) in vec2 pos;
677 	void main()
678 	{
679 	   gl_Position = vec4(pos, 0, 1);
680 	}
681 	)glsl");
682 
683 	const tcu::StringTemplate frag(R"glsl(
684 	#version 450
685 	layout(location = 0) out ${COLOR_TYPE} color;
686 	void main()
687 	{
688 	   color = ${COLOR_TYPE}(${TEST_VALUE},0,0,1);
689 	}
690 	)glsl");
691 
692 	const auto format		= mapVkFormat(m_config.format);
693 	const auto imageFormat	= image::getShaderImageFormatQualifier(format);
694 	const auto imageType	= image::getShaderImageType(format, image::ImageType::IMAGE_TYPE_2D, false);
695 	const auto imageBuffer	= getShaderImageBufferType(format);
696 	const auto colorType	= image::getGlslAttachmentType(m_config.format); // ivec4
697 
698 	const std::map<std::string, std::string>	abbreviations
699 	{
700 		{ std::string("TEST_VALUE"),	std::to_string(testValue)	},
701 		{ std::string("IMAGE_FORMAT"),	std::string(imageFormat)	},
702 		{ std::string("IMAGE_TYPE"),	std::string(imageType)		},
703 		{ std::string("IMAGE_BUFFER"),	std::string(imageBuffer)	},
704 		{ std::string("COLOR_TYPE"),	std::string(colorType)		},
705 	};
706 
707 	programs.glslSources.add("comp") << glu::ComputeSource(
708 											m_config.transitionFrom == VK_QUEUE_COMPUTE_BIT
709 												? producerComp
710 												: consumerComp.specialize(abbreviations));
711 	programs.glslSources.add("vert") << glu::VertexSource(vert);
712 	programs.glslSources.add("frag") << glu::FragmentSource(frag.specialize(abbreviations));
713 }
714 
715 
iterate(void)716 tcu::TestStatus	GPQInstance<VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT>::iterate (void)
717 {
718 	VkResult						deviceStatus		= VK_SUCCESS;
719 	if (!m_device.isValid(deviceStatus))
720 	{
721 		if (VK_ERROR_NOT_PERMITTED_KHR == deviceStatus)
722 			return tcu::TestStatus::pass(getResultName(deviceStatus));
723 		TCU_CHECK(deviceStatus);
724 	}
725 
726 	const InstanceInterface&		vki					= m_context.getInstanceInterface();
727 	const DeviceInterface&			vkd					= m_context.getDeviceInterface();
728 	const VkPhysicalDevice			phys				= m_context.getPhysicalDevice();
729 	const VkDevice					device				= m_device.device;
730 	Allocator&						allocator			= m_device.getAllocator();
731 	const deUint32					producerIndex		= m_device.queueFamilyIndexFrom;
732 	const deUint32					consumerIndex		= m_device.queueFamilyIndexTo;
733 	const VkQueue					producerQueue		= m_device.queueFrom;	DE_UNREF(producerQueue);
734 	const VkQueue					consumerQueue		= m_device.queueTo;		DE_UNREF(consumerQueue);
735 
736 	const uint32_t					width				= m_config.width;
737 	const uint32_t					height				= m_config.height;
738 	const uint32_t					clearComp			= 97;
739 	const VkClearValue				clearColor			= makeClearValueColorU32(clearComp, clearComp, clearComp, clearComp);
740 	const uint32_t					quadCount			= CheckerboardBuilder::blackFieldCount(width, height);
741 	const uint32_t					vertexCount			= 4 * quadCount;
742 	const uint32_t					indexCount			= 6 * quadCount;
743 	const MemoryRequirement			memReqs				= (m_config.enableProtected ? MemoryRequirement::Protected : MemoryRequirement::Any);
744 
745 	VkBufferCreateFlags				buffsCreateFlags	= 0;
746 	if (m_config.enableProtected)	buffsCreateFlags	|= VK_BUFFER_CREATE_PROTECTED_BIT;
747 	if (m_config.enableSparseBinding) buffsCreateFlags	|= VK_BUFFER_CREATE_SPARSE_BINDING_BIT;
748 	const VkBufferUsageFlags		vertBuffUsage		= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
749 	const VkBufferUsageFlags		indexBuffUsage		= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
750 	const VkDeviceSize				vertBuffSize		= vertexCount * mapVkFormat(VK_FORMAT_R32G32_SFLOAT).getPixelSize();
751 	const VkDeviceSize				indexBuffSize		= indexCount * sizeof(uint32_t);
752 	const VkDeviceSize				resultBuffSize		= (width * height * mapVkFormat(m_config.format).getPixelSize());
753 	const VkBufferCreateInfo		vertBuffInfo		= makeBufferCreateInfo(vertBuffSize, vertBuffUsage, {producerIndex}, buffsCreateFlags);
754 	const VkBufferCreateInfo		indexBuffInfo		= makeBufferCreateInfo(indexBuffSize, indexBuffUsage, {producerIndex}, buffsCreateFlags);
755 	const VkBufferCreateInfo		resultBuffInfo		= makeBufferCreateInfo(resultBuffSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
756 	BufferWithMemory				vertexBuffer		(vki, vkd, phys, device, allocator, vertBuffInfo, memReqs, producerQueue);
757 	BufferWithMemory				indexBuffer			(vki, vkd, phys, device, allocator, indexBuffInfo, memReqs, producerQueue);
758 	BufferWithMemory				resultBuffer		(vki, vkd, phys, device, allocator, resultBuffInfo, MemoryRequirement::HostVisible);
759 
760 	const VkDescriptorBufferInfo	dsVertInfo			= makeDescriptorBufferInfo(vertexBuffer.get(), 0ull, vertBuffSize);
761 	const VkDescriptorBufferInfo	dsIndexInfo			= makeDescriptorBufferInfo(indexBuffer.get(), 0ull, indexBuffSize);
762 	Move<VkDescriptorPool>			dsPool				= DescriptorPoolBuilder()
763 															.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
764 															.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
765 															.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
766 	Move<VkDescriptorSetLayout>		dsLayout			= DescriptorSetLayoutBuilder()
767 															.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL)
768 															.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL)
769 															.build(vkd, device);
770 	Move<VkDescriptorSet>			descriptorSet		= makeDescriptorSet(vkd, device, *dsPool, *dsLayout);
771 	DescriptorSetUpdateBuilder()
772 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &dsVertInfo)
773 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &dsIndexInfo)
774 		.update(vkd, device);
775 
776 	VkImageSubresourceRange			colorResourceRange	{};
777 	const VkImageUsageFlags			imageUsage			= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
778 	de::MovePtr<ImageWithMemory>	image				= this->createImage(imageUsage, consumerIndex, consumerQueue);
779 	Move<VkImageView>				view				= createView(**image, colorResourceRange);
780 	Move<VkRenderPass>				renderPass			= makeRenderPass(vkd, device, m_config.format);
781 	Move<VkFramebuffer>				framebuffer			= makeFramebuffer(vkd, device, *renderPass, *view, width, height);
782 	const VkImageMemoryBarrier		colorReadyBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
783 															VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
784 															**image, colorResourceRange);
785 	const VkBufferImageCopy			colorCopyRegion		= makeBufferImageCopy(makeExtent3D(width, height, 1),
786 																			  makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
787 	const VkMemoryBarrier			resultReadyBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
788 	struct PushConstant
789 	{ uint32_t width, height; }		pc					{ width, height };
790 	Move<VkPipelineLayout>			pipelineLayout		= createPipelineLayout<PushConstant>({ *dsLayout });
791 	Move<VkPipeline>				producerPipeline	= createComputePipeline(*pipelineLayout);
792 	Move<VkPipeline>				consumerPipeline	= createGraphicsPipeline(*pipelineLayout, *renderPass);
793 
794 	Move<VkCommandPool>				producerPool		= makeCommandPool(vkd, device, producerIndex);
795 	Move<VkCommandPool>				consumerPool		= makeCommandPool(vkd, device, consumerIndex);
796 	Move<VkCommandBuffer>			producerCmd			= allocateCommandBuffer(vkd, device, *producerPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
797 	Move<VkCommandBuffer>			consumerCmd			= allocateCommandBuffer(vkd, device, *consumerPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
798 
799 	beginCommandBuffer(vkd, *producerCmd);
800 		vkd.cmdBindDescriptorSets(*producerCmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &(*descriptorSet), 0, nullptr);
801 		vkd.cmdBindPipeline(*producerCmd, VK_PIPELINE_BIND_POINT_COMPUTE, *producerPipeline);
802 		vkd.cmdPushConstants(*producerCmd, *pipelineLayout, VK_SHADER_STAGE_ALL, 0, static_cast<uint32_t>(sizeof(PushConstant)), &pc);
803 		vkd.cmdDispatch(*producerCmd, width, height, 2);
804 	endCommandBuffer(vkd, *producerCmd);
805 
806 	beginCommandBuffer(vkd, *consumerCmd);
807 		vkd.cmdBindPipeline(*consumerCmd, VK_PIPELINE_BIND_POINT_GRAPHICS, *consumerPipeline);
808 		vkd.cmdBindIndexBuffer(*consumerCmd, *indexBuffer, 0, VK_INDEX_TYPE_UINT32);
809 		vkd.cmdBindVertexBuffers(*consumerCmd, 0, 1, &static_cast<const VkBuffer&>(*vertexBuffer), &static_cast<const VkDeviceSize&>(0));
810 		beginRenderPass(vkd, *consumerCmd, *renderPass, *framebuffer, makeRect2D(width, height), clearColor);
811 			vkd.cmdDrawIndexed(*consumerCmd, indexCount, 1, 0, 0, 0);
812 		endRenderPass(vkd, *consumerCmd);
813 		vkd.cmdPipelineBarrier(*consumerCmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorReadyBarrier);
814 		vkd.cmdCopyImageToBuffer(*consumerCmd, **image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resultBuffer, 1u, &colorCopyRegion);
815 		vkd.cmdPipelineBarrier(*consumerCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &resultReadyBarrier, 0u, nullptr, 0u, nullptr);
816 	endCommandBuffer(vkd, *consumerCmd);
817 
818 	submitCommands(*producerCmd, *consumerCmd);
819 
820 	resultBuffer.invalidateAlloc(vkd, device);
821 	const tcu::ConstPixelBufferAccess	resultBufferAccess(mapVkFormat(m_config.format), width, height, 1, resultBuffer.getHostPtr());
822 
823 	return verify(resultBufferAccess, GPQCase::testValue, clearComp) ? tcu::TestStatus::pass("") : tcu::TestStatus::fail("");
824 }
825 
iterate(void)826 tcu::TestStatus	GPQInstance<VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT>::iterate (void)
827 {
828 	VkResult						deviceStatus		= VK_SUCCESS;
829 	if (!m_device.isValid(deviceStatus))
830 	{
831 		if (VK_ERROR_NOT_PERMITTED_KHR == deviceStatus)
832 			return tcu::TestStatus::pass(getResultName(deviceStatus));
833 		TCU_CHECK(deviceStatus);
834 	}
835 
836 	const InstanceInterface&		vki					= m_context.getInstanceInterface();
837 	const DeviceInterface&			vkd					= m_context.getDeviceInterface();
838 	const VkPhysicalDevice			phys				= m_context.getPhysicalDevice();
839 	const VkDevice					device				= m_device.device;
840 	Allocator&						allocator			= m_device.getAllocator();
841 	const deUint32					producerIndex		= m_device.queueFamilyIndexFrom;
842 	const deUint32					consumerIndex		= m_device.queueFamilyIndexTo;
843 	const VkQueue					producerQueue		= m_device.queueFrom;	DE_UNREF(producerQueue);
844 	const VkQueue					consumerQueue		= m_device.queueTo;		DE_UNREF(consumerQueue);
845 
846 	const uint32_t					width				= m_config.width;
847 	const uint32_t					height				= m_config.height;
848 	const uint32_t					clearComp			= GPQCase::testValue - 11;
849 	const VkClearValue				clearColor			= makeClearValueColorU32(clearComp, clearComp, clearComp, clearComp);
850 	const uint32_t					quadCount			= CheckerboardBuilder::blackFieldCount(width, height);
851 	const uint32_t					vertexCount			= 4 * quadCount;
852 	const uint32_t					indexCount			= 6 * quadCount;
853 
854 	const VkBufferCreateFlags		graphCreateFlags	= 0;
855 	const MemoryRequirement			graphBuffsMemReqs	= (MemoryRequirement::HostVisible);
856 
857 	const VkBufferUsageFlags		vertBuffUsage		= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
858 	const VkDeviceSize				vertBuffSize		= vertexCount * mapVkFormat(VK_FORMAT_R32G32_SFLOAT).getPixelSize();
859 	const VkBufferCreateInfo		vertBuffInfo		= makeBufferCreateInfo(vertBuffSize, vertBuffUsage, {producerIndex}, graphCreateFlags);
860 	BufferWithMemory				vertexBuffer		(vki, vkd, phys, device, allocator, vertBuffInfo, graphBuffsMemReqs, producerQueue);
861 
862 	const VkBufferUsageFlags		indexBuffUsage		= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
863 	const VkDeviceSize				indexBuffSize		= indexCount * sizeof(uint32_t);
864 	const VkBufferCreateInfo		indexBuffInfo		= makeBufferCreateInfo(indexBuffSize, indexBuffUsage, {producerIndex}, graphCreateFlags);
865 	BufferWithMemory				indexBuffer			(vki, vkd, phys, device, allocator, indexBuffInfo, graphBuffsMemReqs, producerQueue);
866 
867 	VkImageSubresourceRange			producerResRange	{};
868 	const VkImageUsageFlags			producerUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
869 	de::MovePtr<ImageWithMemory>	producerImage		= this->createImage(producerUsage, producerIndex, producerQueue);
870 	Move<VkImageView>				producerView		= createView(**producerImage, producerResRange);
871 	const VkDescriptorImageInfo		producerImageInfo	= makeDescriptorImageInfo(VkSampler(0), *producerView, VK_IMAGE_LAYOUT_GENERAL);
872 
873 	const VkBufferCreateFlags		consumerCreateFlags	= graphCreateFlags;
874 	const MemoryRequirement			consumerMemReqs		= MemoryRequirement::HostVisible | MemoryRequirement::Coherent;
875 	const VkBufferUsageFlags		consumerUsage		= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
876 	const VkDeviceSize				consumerBuffSize	= (width * height * sizeof(uint32_t));
877 	const VkBufferCreateInfo		consumerBuffInfo	= makeBufferCreateInfo(consumerBuffSize, consumerUsage, {consumerIndex}, consumerCreateFlags);
878 	BufferWithMemory				consumerBuffer		(vki, vkd, phys, device, allocator, consumerBuffInfo, consumerMemReqs, consumerQueue);
879 	const VkDescriptorBufferInfo	consumerInfo		= makeDescriptorBufferInfo(*consumerBuffer, 0, consumerBuffSize);
880 
881 	const VkBufferCreateFlags		tmpCreateFlags		= graphCreateFlags;
882 	const MemoryRequirement			tmpMemReqs			= MemoryRequirement::HostVisible | MemoryRequirement::Coherent;
883 	const VkBufferUsageFlags		tmpUsage			= (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
884 	const VkDeviceSize				tmpBuffSize			= (width * height * sizeof(uint32_t));
885 	const VkBufferCreateInfo		tmpBuffInfo			= makeBufferCreateInfo(tmpBuffSize, tmpUsage, {consumerIndex}, tmpCreateFlags);
886 	BufferWithMemory				tmpBuffer			(vki, vkd, phys, device, allocator, tmpBuffInfo, tmpMemReqs, consumerQueue);
887 	const VkBufferImageCopy			tmpCopyRegion		= makeBufferImageCopy(makeExtent3D(width, height, 1),
888 																			  makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
889 
890 	Move<VkDescriptorPool>			dsPool				= DescriptorPoolBuilder()
891 															.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
892 															.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
893 															.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
894 	Move<VkDescriptorSetLayout>		dsLayout			= DescriptorSetLayoutBuilder()
895 															.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_ALL)
896 															.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL)
897 															.build(vkd, device);
898 	Move<VkDescriptorSet>			descriptorSet		= makeDescriptorSet(vkd, device, *dsPool, *dsLayout);
899 
900 	DescriptorSetUpdateBuilder()
901 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &producerImageInfo)
902 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &consumerInfo)
903 		.update(vkd, device);
904 
905 	Move<VkRenderPass>				renderPass			= makeRenderPass(vkd, device, m_config.format);
906 	Move<VkFramebuffer>				framebuffer			= makeFramebuffer(vkd, device, *renderPass, *producerView, width, height);
907 
908 	const VkImageMemoryBarrier		producerReadyBarrier= makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_NONE,
909 															VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
910 															**producerImage, producerResRange);
911 //	const VkBufferMemoryBarrier		consumerReadyBarrier= makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_NONE,
912 //																				  *consumerBuffer, 0, consumerBuffSize,
913 //																				  consumerIndex, consumerIndex);
914 	//const VkMemoryBarrier			tmpReadyBarrier		= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
915 //	const VkBufferMemoryBarrier		tmpReadyBarrier		= makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_NONE,
916 //																				  *tmpBuffer, 0, tmpBuffSize,
917 //																				  consumerIndex, consumerIndex);
918 	const VkBufferMemoryBarrier		consumerBarriers[]	{	makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_NONE,
919 																					*consumerBuffer, 0, consumerBuffSize,
920 																					consumerIndex, consumerIndex),
921 															makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_NONE,
922 																					*tmpBuffer, 0, tmpBuffSize,
923 																					consumerIndex, consumerIndex) };
924 	struct PushConstant
925 	{ uint32_t width, height; }		pc					{ width, height };
926 	Move<VkPipelineLayout>			pipelineLayout		= createPipelineLayout<PushConstant>({ *dsLayout });
927 	Move<VkPipeline>				producerPipeline	= createGraphicsPipeline(*pipelineLayout, *renderPass);
928 	Move<VkPipeline>				consumerPipeline	= createComputePipeline(*pipelineLayout);
929 
930 	Move<VkCommandPool>				producerPool		= makeCommandPool(vkd, device, producerIndex);
931 	Move<VkCommandPool>				consumerPool		= makeCommandPool(vkd, device, consumerIndex);
932 	Move<VkCommandBuffer>			producerCmd			= allocateCommandBuffer(vkd, device, *producerPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
933 	Move<VkCommandBuffer>			consumerCmd			= allocateCommandBuffer(vkd, device, *consumerPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
934 
935 	{
936 		std::vector<float>		vertices;
937 		std::vector<uint32_t>	indices;
938 		CheckerboardBuilder	builder(width, height);
939 		builder.buildVerticesAndIndices(vertices, indices);
940 		DE_ASSERT(vertices.size() == (vertexCount * 2));
941 		DE_ASSERT(indices.size() == indexCount);
942 		std::copy(vertices.begin(), vertices.end(), begin<float>(vertexBuffer.getHostPtr()));
943 		std::copy(indices.begin(), indices.end(), begin<uint32_t>(indexBuffer.getHostPtr()));
944 		vertexBuffer.flushAlloc(vkd, device);
945 		indexBuffer.flushAlloc(vkd, device);
946 	}
947 
948 	beginCommandBuffer(vkd, *producerCmd);
949 		vkd.cmdBindPipeline(*producerCmd, VK_PIPELINE_BIND_POINT_GRAPHICS, *producerPipeline);
950 		vkd.cmdBindVertexBuffers(*producerCmd, 0, 1, &static_cast<const VkBuffer&>(*vertexBuffer), &static_cast<const VkDeviceSize&>(0));
951 		vkd.cmdBindIndexBuffer(*producerCmd, *indexBuffer, 0, VK_INDEX_TYPE_UINT32);
952 		beginRenderPass(vkd, *producerCmd, *renderPass, *framebuffer, makeRect2D(width, height), clearColor);
953 			vkd.cmdDrawIndexed(*producerCmd, indexCount, 1, 0, 0, 0);
954 		endRenderPass(vkd, *producerCmd);
955 		vkd.cmdPipelineBarrier(*producerCmd, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VkDependencyFlags(0),
956 							   0u, nullptr, 0u, nullptr, 1u, &producerReadyBarrier);
957 	endCommandBuffer(vkd, *producerCmd);
958 
959 	beginCommandBuffer(vkd, *consumerCmd);
960 		vkd.cmdBindPipeline(*consumerCmd, VK_PIPELINE_BIND_POINT_COMPUTE, *consumerPipeline);
961 		vkd.cmdBindDescriptorSets(*consumerCmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, nullptr);
962 		vkd.cmdCopyImageToBuffer(*consumerCmd, **producerImage, VK_IMAGE_LAYOUT_GENERAL, *tmpBuffer, 1u, &tmpCopyRegion);
963 		vkd.cmdPushConstants(*consumerCmd, *pipelineLayout, VK_SHADER_STAGE_ALL, 0, static_cast<uint32_t>(sizeof(PushConstant)), &pc);
964 		vkd.cmdDispatch(*consumerCmd, width, height, 1);
965 		vkd.cmdPipelineBarrier(*consumerCmd, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VkDependencyFlags(0),
966 							   0, nullptr, DE_LENGTH_OF_ARRAY(consumerBarriers), consumerBarriers, 0, nullptr);
967 	endCommandBuffer(vkd, *consumerCmd);
968 
969 	submitCommands(*producerCmd, *consumerCmd);
970 
971 	tmpBuffer.invalidateAlloc(vkd, device);
972 	const tcu::ConstPixelBufferAccess	tmpBufferAccess(mapVkFormat(m_config.format), width, height, 1, tmpBuffer.getHostPtr());
973 	const bool tmpRes = verify(tmpBufferAccess, GPQCase::testValue, clearComp);
974 
975 	consumerBuffer.invalidateAlloc(vkd, device);
976 	const tcu::ConstPixelBufferAccess	resultBufferAccess(mapVkFormat(m_config.format), width, height, 1, consumerBuffer.getHostPtr());
977 
978 	return (tmpRes && verify(resultBufferAccess, (GPQCase::testValue + 1), (clearComp + 1))) ? tcu::TestStatus::pass("") : tcu::TestStatus::fail("");
979 }
980 
verify(const BufferAccess & result,deUint32 blackColor,deUint32 whiteColor) const981 bool GPQInstanceBase::verify (const BufferAccess& result, deUint32 blackColor, deUint32 whiteColor) const
982 {
983 	bool ok = true;
984 
985 	for (deUint32 y = 0; ok && y < m_config.height; ++y)
986 	{
987 		for (deUint32 x = 0; ok && x < m_config.width; ++x)
988 		{
989 			const deUint32 color = result.getPixelT<deUint32>(x, y).x();
990 			if (((x + y) % 2) == 0)
991 			{
992 				ok = color == blackColor;
993 			}
994 			else
995 			{
996 				ok = color == whiteColor;
997 			}
998 		}
999 	}
1000 	return ok;
1001 }
1002 
1003 } // anonymous
1004 
createGlobalPriorityQueueTests(tcu::TestContext & testCtx)1005 tcu::TestCaseGroup* createGlobalPriorityQueueTests (tcu::TestContext& testCtx)
1006 {
1007 	typedef std::pair<VkQueueFlagBits, const char*> TransitionItem;
1008 	TransitionItem const transitions[]
1009 	{
1010 		{ VK_QUEUE_GRAPHICS_BIT,	"graphics"	},
1011 		{ VK_QUEUE_COMPUTE_BIT,		"compute"	},
1012 	};
1013 
1014 	auto mkGroupName = [](const TransitionItem& from, const TransitionItem& to) -> std::string
1015 	{
1016 		return std::string("from_") + from.second + std::string("_to_") + to.second;
1017 	};
1018 
1019 	std::pair<VkQueueFlags, const char*>
1020 			const modifiers[]
1021 	{
1022 		{ 0,													"no_modifiers"		},
1023 		{ VK_QUEUE_SPARSE_BINDING_BIT,							"sparse"			},
1024 		{ VK_QUEUE_PROTECTED_BIT,								"protected"			},
1025 		{ VK_QUEUE_SPARSE_BINDING_BIT|VK_QUEUE_PROTECTED_BIT,	"sparse_protected"	},
1026 	};
1027 
1028 	std::pair<VkQueueGlobalPriorityKHR, const char*>
1029 			const prios[]
1030 	{
1031 		{ VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR,			"low"		},
1032 		{ VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR,		"medium"	},
1033 		{ VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR,		"high"		},
1034 		{ VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR,	"realtime"	},
1035 	};
1036 
1037 	std::pair<SyncType, const char*>
1038 			const syncs[]
1039 	{
1040 		{ SyncType::None,		"no_sync"	},
1041 		{ SyncType::Semaphore,	"semaphore"	},
1042 	};
1043 
1044 	const uint32_t	dim0	= 34;
1045 	const uint32_t	dim1	= 25;
1046 	bool			swap	= true;
1047 
1048 	auto rootGroup = new tcu::TestCaseGroup(testCtx, "global_priority_transition", "Global Priority Queue Tests");
1049 
1050 	for (const auto& prio : prios)
1051 	{
1052 		auto prioGroup = new tcu::TestCaseGroup(testCtx, prio.second, "");
1053 
1054 		for (const auto& sync : syncs)
1055 		{
1056 			auto syncGroup = new tcu::TestCaseGroup(testCtx, sync.second, "");
1057 
1058 			for (const auto& mod : modifiers)
1059 			{
1060 				auto modGroup = new tcu::TestCaseGroup(testCtx, mod.second, "");
1061 
1062 				for (const auto& transitionFrom : transitions)
1063 				{
1064 					for (const auto& transitionTo : transitions)
1065 					{
1066 						if (transitionFrom != transitionTo)
1067 						{
1068 							TestConfig	cfg{};
1069 							cfg.transitionFrom		= transitionFrom.first;
1070 							cfg.transitionTo		= transitionTo.first;
1071 							cfg.priorityFrom		= prio.first;
1072 							cfg.priorityTo			= prio.first;
1073 							cfg.syncType			= sync.first;
1074 							cfg.enableProtected		= (mod.first & VK_QUEUE_PROTECTED_BIT) != 0;
1075 							cfg.enableSparseBinding	= (mod.first & VK_QUEUE_SPARSE_BINDING_BIT) != 0;
1076 							// Note that format is changing in GPQCase::checkSupport(...)
1077 							cfg.format				= VK_FORMAT_R32G32B32A32_SFLOAT;
1078 							cfg.width				= swap ? dim0 : dim1;
1079 							cfg.height				= swap ? dim1 : dim0;
1080 
1081 							swap ^= true;
1082 
1083 							modGroup->addChild(new GPQCase(testCtx, mkGroupName(transitionFrom, transitionTo), cfg));
1084 						}
1085 					}
1086 				}
1087 				syncGroup->addChild(modGroup);
1088 			}
1089 			prioGroup->addChild(syncGroup);
1090 		}
1091 		rootGroup->addChild(prioGroup);
1092 	}
1093 
1094 	return rootGroup;
1095 }
1096 
1097 } // synchronization
1098 } // vkt
1099