1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Advanced Micro Devices, Inc.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests for VK_AMD_buffer_marker
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktApiBufferMarkerTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vktExternalMemoryUtil.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "deUniquePtr.hpp"
38 #include "deSharedPtr.hpp"
39 #include "deRandom.hpp"
40 
41 #include <vector>
42 
43 namespace vkt
44 {
45 namespace api
46 {
47 namespace
48 {
49 using namespace vk;
50 using de::UniquePtr;
51 using de::MovePtr;
52 using de::SharedPtr;
53 using namespace vkt::ExternalMemoryUtil;
54 
55 template<typename T>
dataOrNullPtr(const std::vector<T> & v)56 inline const T* dataOrNullPtr(const std::vector<T>& v)
57 {
58 	return (v.empty() ? DE_NULL : &v[0]);
59 }
60 
61 template<typename T>
dataOrNullPtr(std::vector<T> & v)62 inline T* dataOrNullPtr(std::vector<T>& v)
63 {
64 	return (v.empty() ? DE_NULL : &v[0]);
65 }
66 
67 //! Common test data related to the device
68 struct WorkingDevice
69 {
70 	Move<VkDevice>          logicalDevice;
71 	MovePtr<DeviceDriver>   deviceDriver;
72 	MovePtr<Allocator>      allocator;
73 	VkQueue                 queue;
74 	deUint32                queueFamilyIdx;
75 	VkQueueFamilyProperties queueProps;
76 };
77 
queueFamilyMatchesTestCase(const VkQueueFamilyProperties & props,VkQueueFlagBits testQueue)78 bool queueFamilyMatchesTestCase(const VkQueueFamilyProperties& props, VkQueueFlagBits testQueue)
79 {
80 	// The goal is to find a queue family that most accurately represents the required queue flag.  For example, if flag is
81 	// VK_QUEUE_TRANSFER_BIT, we want to target transfer-only queues for such a test case rather than universal queues which
82 	// may include VK_QUEUE_TRANSFER_BIT along with other queue flags.
83 	const VkQueueFlags flags = props.queueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT);
84 
85 	// for VK_QUEUE_TRANSFER_BIT, target transfer-only queues:
86 	if (testQueue == VK_QUEUE_TRANSFER_BIT)
87 		return (flags == VK_QUEUE_TRANSFER_BIT);
88 
89 	// for VK_QUEUE_COMPUTE_BIT, target compute only queues
90 	if (testQueue == VK_QUEUE_COMPUTE_BIT)
91 		return ((flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)) == VK_QUEUE_COMPUTE_BIT);
92 
93 	// for VK_QUEUE_GRAPHICS_BIT, target universal queues (queues which support graphics)
94 	if (testQueue == VK_QUEUE_GRAPHICS_BIT)
95 		return ((flags & VK_QUEUE_GRAPHICS_BIT) != 0);
96 
97 	DE_FATAL("Unexpected test queue flag");
98 
99 	return false;
100 }
101 
102 // We create a custom device because we don't want to always use the universal queue.
createDeviceWithExtension(Context & context,WorkingDevice & wd,VkQueueFlagBits testQueue,bool hostPtr)103 void createDeviceWithExtension (Context& context, WorkingDevice& wd, VkQueueFlagBits testQueue, bool hostPtr)
104 {
105 	const PlatformInterface&	vkp				= context.getPlatformInterface();
106 	const VkInstance			instance		= context.getInstance();
107 	const InstanceInterface&	instanceDriver	= context.getInstanceInterface();
108 	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
109 
110 	// Create a device with extension enabled and a queue with a family which supports the buffer marker extension
111 	const std::vector<VkQueueFamilyProperties>	queueFamilyProperties	= getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice);
112 	const float									queuePriority			= 1.0f;
113 	VkDeviceQueueCreateInfo						queueCreateInfo;
114 	deMemset(&queueCreateInfo, 0, sizeof(queueCreateInfo));
115 
116 	for (deUint32 familyIdx = 0; familyIdx < queueFamilyProperties.size(); ++familyIdx)
117 	{
118 		if (queueFamilyMatchesTestCase(queueFamilyProperties[familyIdx], testQueue) &&
119 			queueFamilyProperties[familyIdx].queueCount > 0)
120 		{
121 			queueCreateInfo.sType				= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
122 			queueCreateInfo.pNext				= DE_NULL;
123 			queueCreateInfo.pQueuePriorities	= &queuePriority;
124 			queueCreateInfo.queueCount			= 1;
125 			queueCreateInfo.queueFamilyIndex	= familyIdx;
126 
127 			break;
128 		}
129 	}
130 
131 	if (queueCreateInfo.queueCount == 0)
132 	{
133 		TCU_THROW(NotSupportedError, "No compatible queue family for this test case");
134 	}
135 
136 	std::vector<const char*> cstrDeviceExtensions;
137 
138 	cstrDeviceExtensions.push_back("VK_AMD_buffer_marker");
139 
140 	if (hostPtr)
141 		cstrDeviceExtensions.push_back("VK_EXT_external_memory_host");
142 
143 	const VkDeviceCreateInfo deviceInfo =
144 	{
145 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,				// VkStructureType					sType;
146 		DE_NULL,											// const void*						pNext;
147 		0u,													// VkDeviceCreateFlags				flags;
148 		1,													// deUint32							queueCreateInfoCount;
149 		&queueCreateInfo,									// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
150 		0u,													// deUint32							enabledLayerCount;
151 		DE_NULL,											// const char* const*				ppEnabledLayerNames;
152 		static_cast<deUint32>(cstrDeviceExtensions.size()),	// deUint32							enabledExtensionCount;
153 		dataOrNullPtr(cstrDeviceExtensions),				// const char* const*				ppEnabledExtensionNames;
154 		&context.getDeviceFeatures(),						// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
155 	};
156 
157 	wd.logicalDevice	= createDevice(vkp, instance, instanceDriver, physicalDevice, &deviceInfo);
158 	wd.deviceDriver		= MovePtr<DeviceDriver>(new DeviceDriver(vkp, instance, *wd.logicalDevice));
159 	wd.allocator		= MovePtr<Allocator>(new SimpleAllocator(*wd.deviceDriver, *wd.logicalDevice, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice)));
160 	wd.queueFamilyIdx	= queueCreateInfo.queueFamilyIndex;
161 	wd.queue			= getDeviceQueue(*wd.deviceDriver, *wd.logicalDevice, wd.queueFamilyIdx, 0u);
162 	wd.queueProps		= queueFamilyProperties[queueCreateInfo.queueFamilyIndex];
163 }
164 
checkMarkerBuffer(const DeviceInterface & vk,VkDevice device,const MovePtr<vk::Allocation> & memory,size_t offset,const std::vector<deUint32> & expected)165 bool checkMarkerBuffer	(const DeviceInterface& vk, VkDevice device, const MovePtr<vk::Allocation>& memory, size_t offset,
166 						 const std::vector<deUint32>& expected)
167 {
168 	invalidateMappedMemoryRange(vk, device, memory->getMemory(), memory->getOffset(), VK_WHOLE_SIZE);
169 
170 	const deUint32* data = reinterpret_cast<const deUint32*>(static_cast<const char*>(memory->getHostPtr()) + offset);
171 
172 	for (size_t i = 0; i < expected.size(); ++i)
173 	{
174 		if (data[i] != expected[i])
175 			return false;
176 	}
177 
178 	return true;
179 }
180 
181 struct BaseTestParams
182 {
183 	VkQueueFlagBits			testQueue;	// Queue type that this test case targets
184 	VkPipelineStageFlagBits stage;		// Pipeline stage where any marker writes for this test case occur in
185 	deUint32				size;		// Number of buffer markers
186 	bool					useHostPtr;	// Whether to use host pointer as backing buffer memory
187 };
188 
chooseExternalMarkerMemoryType(const DeviceInterface & vkd,VkDevice device,VkExternalMemoryHandleTypeFlagBits externalType,deUint32 allowedBits,MovePtr<ExternalHostMemory> & hostMemory)189 deUint32 chooseExternalMarkerMemoryType(const DeviceInterface&				vkd,
190 										VkDevice							device,
191 										VkExternalMemoryHandleTypeFlagBits	externalType,
192 										deUint32							allowedBits,
193 										MovePtr<ExternalHostMemory>&		hostMemory)
194 {
195 	VkMemoryHostPointerPropertiesEXT props =
196 	{
197 		vk::VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
198 		DE_NULL,
199 		0u,
200 	};
201 
202 	if (vkd.getMemoryHostPointerPropertiesEXT(device, externalType, hostMemory->data, &props) == VK_SUCCESS)
203 	{
204 		allowedBits &= props.memoryTypeBits;
205 	}
206 
207 	deUint32 index = 0;
208 
209 	while ((index < VK_MAX_MEMORY_TYPES) && ((allowedBits & 0x1) == 0))
210 	{
211 		index++;
212 		allowedBits >>= 1;
213 	}
214 
215 	return index;
216 }
217 
218 class ExternalHostAllocation : public Allocation
219 {
220 public:
ExternalHostAllocation(Move<VkDeviceMemory> mem,void * hostPtr)221 	ExternalHostAllocation(Move<VkDeviceMemory> mem, void* hostPtr) : Allocation(*mem, (VkDeviceSize)0, hostPtr), m_memHolder(mem) { }
222 
223 private:
224 	const Unique<VkDeviceMemory>	m_memHolder;
225 };
226 
createMarkerBufferMemory(const InstanceInterface & vki,const DeviceInterface & vkd,VkPhysicalDevice physicalDevice,VkDevice device,VkBuffer buffer,MovePtr<Allocator> & allocator,const MemoryRequirement allocRequirement,bool externalHostPtr,MovePtr<ExternalHostMemory> & hostMemory,MovePtr<Allocation> & deviceMemory)227 void createMarkerBufferMemory(const InstanceInterface&		vki,
228 							 const DeviceInterface&			vkd,
229 							 VkPhysicalDevice				physicalDevice,
230 							 VkDevice						device,
231 							 VkBuffer						buffer,
232 							 MovePtr<Allocator>&			allocator,
233 							 const MemoryRequirement		allocRequirement,
234 							 bool							externalHostPtr,
235 							 MovePtr<ExternalHostMemory>&	hostMemory,
236 							 MovePtr<Allocation>&			deviceMemory)
237 {
238 	VkMemoryRequirements memReqs = getBufferMemoryRequirements(vkd, device, buffer);
239 
240 	if (externalHostPtr == false)
241 	{
242 		deviceMemory = allocator->allocate(memReqs, allocRequirement);
243 	}
244 	else
245 	{
246 		const VkExternalMemoryHandleTypeFlagBits externalType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
247 
248 		const VkPhysicalDeviceExternalMemoryHostPropertiesEXT hostProps = getPhysicalDeviceExternalMemoryHostProperties(vki, physicalDevice);
249 
250 		hostMemory = MovePtr<ExternalHostMemory>(new ExternalHostMemory(memReqs.size, hostProps.minImportedHostPointerAlignment));
251 
252 		const deUint32 externalMemType = chooseExternalMarkerMemoryType(vkd, device, externalType, memReqs.memoryTypeBits, hostMemory);
253 
254 		if (externalMemType == VK_MAX_MEMORY_TYPES)
255 		{
256 			TCU_FAIL("Failed to find compatible external host memory type for marker buffer");
257 		}
258 
259 		const VkImportMemoryHostPointerInfoEXT	importInfo =
260 		{
261 			VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
262 			DE_NULL,
263 			externalType,
264 			hostMemory->data
265 		};
266 
267 		const VkMemoryAllocateInfo				info =
268 		{
269 			VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
270 			(const void*)&importInfo,
271 			hostMemory->size,
272 			externalMemType
273 		};
274 
275 		deviceMemory = MovePtr<Allocation>(new ExternalHostAllocation(allocateMemory(vkd, device, &info), hostMemory->data));
276 	}
277 
278 	VK_CHECK(vkd.bindBufferMemory(device, buffer, deviceMemory->getMemory(), deviceMemory->getOffset()));
279 }
280 
bufferMarkerSequential(Context & context,BaseTestParams params)281 tcu::TestStatus bufferMarkerSequential(Context& context, BaseTestParams params)
282 {
283 	WorkingDevice wd;
284 
285 	createDeviceWithExtension(context, wd, params.testQueue, params.useHostPtr);
286 
287 	const DeviceInterface&			vk(*wd.deviceDriver);
288 	const VkDevice					device(*wd.logicalDevice);
289 	const VkDeviceSize				markerBufferSize(params.size * sizeof(deUint32));
290 	Move<VkBuffer>					markerBuffer(makeBuffer(vk, device, markerBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
291 	MovePtr<ExternalHostMemory>		hostMemory;
292 	MovePtr<Allocation>				markerMemory;
293 
294 	createMarkerBufferMemory(context.getInstanceInterface(), vk, context.getPhysicalDevice(), device,
295 							 *markerBuffer, wd.allocator, MemoryRequirement::HostVisible, params.useHostPtr, hostMemory, markerMemory);
296 
297 	de::Random						rng(12345 ^ params.size);
298 	std::vector<deUint32>			expected(params.size);
299 
300 	for (size_t i = 0; i < params.size; ++i)
301 		expected[i] = rng.getUint32();
302 
303 	deMemcpy(markerMemory->getHostPtr(), &expected[0], static_cast<size_t>(markerBufferSize));
304 	flushMappedMemoryRange(vk, device, markerMemory->getMemory(), markerMemory->getOffset(), VK_WHOLE_SIZE);
305 
306 	const Unique<VkCommandPool>		cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, wd.queueFamilyIdx));
307 	const Unique<VkCommandBuffer>	cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
308 
309 	beginCommandBuffer(vk, *cmdBuffer);
310 
311 	for (size_t i = 0; i < params.size; ++i)
312 	{
313 		vk.cmdWriteBufferMarkerAMD(*cmdBuffer, params.stage, *markerBuffer, static_cast<VkDeviceSize>(sizeof(deUint32) * i), expected[i]);
314 	}
315 
316 	const VkMemoryBarrier memoryDep =
317 	{
318 		VK_STRUCTURE_TYPE_MEMORY_BARRIER,
319 		DE_NULL,
320 		VK_ACCESS_TRANSFER_WRITE_BIT,
321 		VK_ACCESS_HOST_READ_BIT,
322 	};
323 
324 	vk.cmdPipelineBarrier(*cmdBuffer, params.stage, VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memoryDep, 0, DE_NULL, 0, DE_NULL);
325 
326 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
327 
328 	submitCommandsAndWait(vk, device, wd.queue, *cmdBuffer);
329 
330 	if (!checkMarkerBuffer(vk, device, markerMemory, 0, expected))
331 		return tcu::TestStatus::fail("Some marker values were incorrect");
332 
333 	return tcu::TestStatus::pass("Pass");
334 }
335 
bufferMarkerOverwrite(Context & context,BaseTestParams params)336 tcu::TestStatus bufferMarkerOverwrite(Context& context, BaseTestParams params)
337 {
338 	WorkingDevice wd;
339 
340 	createDeviceWithExtension(context, wd, params.testQueue, params.useHostPtr);
341 
342 	const DeviceInterface&			vk(*wd.deviceDriver);
343 	const VkDevice					device(*wd.logicalDevice);
344 	const VkDeviceSize				markerBufferSize(params.size * sizeof(deUint32));
345 	Move<VkBuffer>					markerBuffer(makeBuffer(vk, device, markerBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
346 	MovePtr<ExternalHostMemory>		hostMemory;
347 	MovePtr<Allocation>				markerMemory;
348 
349 	createMarkerBufferMemory(context.getInstanceInterface(), vk, context.getPhysicalDevice(), device,
350 							 *markerBuffer, wd.allocator, MemoryRequirement::HostVisible, params.useHostPtr, hostMemory, markerMemory);
351 
352 	de::Random						rng(12345 ^ params.size);
353 	std::vector<deUint32>			expected(params.size);
354 
355 	for (size_t i = 0; i < params.size; ++i)
356 		expected[i] = 0;
357 
358 	deMemcpy(markerMemory->getHostPtr(), &expected[0], static_cast<size_t>(markerBufferSize));
359 	flushMappedMemoryRange(vk, device, markerMemory->getMemory(), markerMemory->getOffset(), VK_WHOLE_SIZE);
360 
361 	const Unique<VkCommandPool>		cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, wd.queueFamilyIdx));
362 	const Unique<VkCommandBuffer>	cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
363 
364 	beginCommandBuffer(vk, *cmdBuffer);
365 
366 	for (deUint32 i = 0; i < params.size * 10; ++i)
367 	{
368 		const deUint32 slot  = rng.getUint32() % static_cast<deUint32>(params.size);
369 		const deUint32 value = i;
370 
371 		expected[slot] = value;
372 
373 		vk.cmdWriteBufferMarkerAMD(*cmdBuffer, params.stage, *markerBuffer, static_cast<VkDeviceSize>(sizeof(deUint32) * slot), expected[slot]);
374 	}
375 
376 	const VkMemoryBarrier memoryDep = {
377 		VK_STRUCTURE_TYPE_MEMORY_BARRIER,
378 		DE_NULL,
379 		VK_ACCESS_TRANSFER_WRITE_BIT,
380 		VK_ACCESS_HOST_READ_BIT,
381 	};
382 
383 	vk.cmdPipelineBarrier(*cmdBuffer, params.stage, VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memoryDep, 0, DE_NULL, 0, DE_NULL);
384 
385 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
386 
387 	submitCommandsAndWait(vk, device, wd.queue, *cmdBuffer);
388 
389 	if (!checkMarkerBuffer(vk, device, markerMemory, 0, expected))
390 		return tcu::TestStatus::fail("Some marker values were incorrect");
391 
392 	return tcu::TestStatus::pass("Pass");
393 }
394 
395 enum MemoryDepMethod
396 {
397 	MEMORY_DEP_DRAW,
398 	MEMORY_DEP_DISPATCH,
399 	MEMORY_DEP_COPY
400 };
401 
402 struct MemoryDepParams
403 {
404 	BaseTestParams			base;
405 	MemoryDepMethod			method;
406 };
407 
408 enum MemoryDepOwner
409 {
410 	MEMORY_DEP_OWNER_NOBODY = 0,
411 	MEMORY_DEP_OWNER_MARKER = 1,
412 	MEMORY_DEP_OWNER_NON_MARKER = 2
413 };
414 
computeMemoryDepBarrier(MemoryDepMethod method,MemoryDepOwner owner,VkAccessFlags * memoryDepAccess,VkPipelineStageFlags * executionScope)415 void computeMemoryDepBarrier(MemoryDepMethod			method,
416 							 MemoryDepOwner				owner,
417 							 VkAccessFlags*				memoryDepAccess,
418 							 VkPipelineStageFlags*		executionScope)
419 {
420 	DE_ASSERT(owner != MEMORY_DEP_OWNER_NOBODY);
421 
422 	if (owner == MEMORY_DEP_OWNER_MARKER)
423 	{
424 		*memoryDepAccess = VK_ACCESS_TRANSFER_WRITE_BIT;
425 		*executionScope  = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
426 	}
427 	else
428 	{
429 		if (method == MEMORY_DEP_COPY)
430 		{
431 			*memoryDepAccess = VK_ACCESS_TRANSFER_WRITE_BIT;
432 			*executionScope  = VK_PIPELINE_STAGE_TRANSFER_BIT;
433 		}
434 		else if (method == MEMORY_DEP_DISPATCH)
435 		{
436 			*memoryDepAccess = VK_ACCESS_SHADER_WRITE_BIT;
437 			*executionScope  = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
438 		}
439 		else
440 		{
441 			*memoryDepAccess = VK_ACCESS_SHADER_WRITE_BIT;
442 			*executionScope  = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
443 		}
444 	}
445 }
446 
447 // Randomly do buffer marker writes and other operations (draws, dispatches) that shader-write to a shared buffer.  Insert pipeline barriers
448 // when necessary and make sure that the synchronization between marker writes and non-marker writes are correctly handled by the barriers.
bufferMarkerMemoryDep(Context & context,MemoryDepParams params)449 tcu::TestStatus bufferMarkerMemoryDep(Context& context, MemoryDepParams params)
450 {
451 	WorkingDevice wd;
452 
453 	createDeviceWithExtension(context, wd, params.base.testQueue, params.base.useHostPtr);
454 
455 	VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
456 
457 	if ((params.method == MEMORY_DEP_DRAW) || (params.method == MEMORY_DEP_DISPATCH))
458 		usageFlags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
459 	else
460 		usageFlags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
461 
462 	const deUint32					numIters(1000);
463 	const DeviceInterface&			vk(*wd.deviceDriver);
464 	const VkDevice					device(*wd.logicalDevice);
465 	const deUint32					size(params.base.size);
466 	const VkDeviceSize				markerBufferSize(params.base.size * sizeof(deUint32));
467 	Move<VkBuffer>					markerBuffer(makeBuffer(vk, device, params.base.size * sizeof(deUint32), usageFlags));
468 	MovePtr<ExternalHostMemory>		hostMemory;
469 	MovePtr<Allocation>				markerMemory;
470 
471 	createMarkerBufferMemory(context.getInstanceInterface(), vk, context.getPhysicalDevice(), device,
472 		*markerBuffer, wd.allocator, MemoryRequirement::HostVisible, params.base.useHostPtr, hostMemory, markerMemory);
473 
474 	de::Random						rng(size ^ params.base.size);
475 	std::vector<deUint32>			expected(params.base.size, 0);
476 
477 	Move<VkDescriptorPool>			descriptorPool;
478 	Move<VkDescriptorSetLayout>		descriptorSetLayout;
479 	Move<VkDescriptorSet>			descriptorSet;
480 	Move<VkPipelineLayout>			pipelineLayout;
481 	VkShaderStageFlags				pushConstantStage = 0;
482 
483 	if ((params.method == MEMORY_DEP_DRAW) || (params.method == MEMORY_DEP_DISPATCH))
484 	{
485 		DescriptorPoolBuilder descriptorPoolBuilder;
486 
487 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
488 		descriptorPool = descriptorPoolBuilder.build(vk, device, 0, 1u);
489 
490 		DescriptorSetLayoutBuilder setLayoutBuilder;
491 
492 		setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
493 		descriptorSetLayout = setLayoutBuilder.build(vk, device);
494 
495 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
496 		{
497 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
498 			DE_NULL,											// const void*					pNext;
499 			*descriptorPool,									// VkDescriptorPool				descriptorPool;
500 			1u,													// deUint32						setLayoutCount;
501 			&descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
502 		};
503 
504 		descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocateInfo);
505 
506 		VkDescriptorBufferInfo markerBufferInfo = { *markerBuffer, 0, VK_WHOLE_SIZE };
507 
508 		VkWriteDescriptorSet writeSet[] =
509 		{
510 			{
511 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType                  sType;
512 				DE_NULL,								// const void*                      pNext;
513 				descriptorSet.get(),					// VkDescriptorSet                  dstSet;
514 				0,										// uint32_t                         dstBinding;
515 				0,										// uint32_t                         dstArrayElement;
516 				1,										// uint32_t                         descriptorCount;
517 				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// VkDescriptorType                 descriptorType;
518 				DE_NULL,								// const VkDescriptorImageInfo*     pImageInfo;
519 				&markerBufferInfo,						// const VkDescriptorBufferInfo*    pBufferInfo;
520 				DE_NULL									// const VkBufferView*              pTexelBufferViev
521 			}
522 		};
523 
524 		vk.updateDescriptorSets(device, DE_LENGTH_OF_ARRAY(writeSet), writeSet, 0, DE_NULL);
525 
526 		VkDescriptorSetLayout setLayout = descriptorSetLayout.get();
527 
528 		pushConstantStage = (params.method == MEMORY_DEP_DISPATCH ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT);
529 
530 		const VkPushConstantRange pushConstantRange =
531 		{
532 			pushConstantStage,	// VkShaderStageFlags    stageFlags;
533 			0u,					// uint32_t              offset;
534 			2*sizeof(deUint32),	// uint32_t              size;
535 		};
536 
537 		const VkPipelineLayoutCreateInfo pipelineLayoutInfo =
538 		{
539 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
540 			DE_NULL,											// const void*					pNext;
541 			(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
542 			1u,													// deUint32						setLayoutCount;
543 			&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
544 			1u,													// deUint32						pushConstantRangeCount;
545 			&pushConstantRange,									// const VkPushConstantRange*	pPushConstantRanges;
546 		};
547 
548 		pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutInfo);
549 	}
550 
551 	Move<VkRenderPass>		renderPass;
552 	Move<VkFramebuffer>		fbo;
553 	Move<VkPipeline>		pipeline;
554 	Move<VkShaderModule>	vertexModule;
555 	Move<VkShaderModule>	fragmentModule;
556 	Move<VkShaderModule>	computeModule;
557 
558 	if (params.method == MEMORY_DEP_DRAW)
559 	{
560 		const VkSubpassDescription subpassInfo =
561 		{
562 			0,									// VkSubpassDescriptionFlags       flags;
563 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint             pipelineBindPoint;
564 			0,									// uint32_t                        inputAttachmentCount;
565 			DE_NULL,							// const VkAttachmentReference*    pInputAttachments;
566 			0,									// uint32_t                        colorAttachmentCount;
567 			DE_NULL,							// const VkAttachmentReference*    pColorAttachments;
568 			0,									// const VkAttachmentReference*    pResolveAttachments;
569 			DE_NULL,							// const VkAttachmentReference*    pDepthStencilAttachment;
570 			0,									// uint32_t                        preserveAttachmentCount;
571 			DE_NULL								// const uint32_t*                 pPreserveAttachments;
572 		};
573 
574 		const VkRenderPassCreateInfo renderPassInfo =
575 		{
576 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType                   sType;
577 			DE_NULL,									// const void*                       pNext;
578 			0,											// VkRenderPassCreateFlags           flags;
579 			0,											// uint32_t                          attachmentCount;
580 			DE_NULL,									// const VkAttachmentDescription*    pAttachments;
581 			1,											// uint32_t                          subpassCount;
582 			&subpassInfo,								// const VkSubpassDescription*       pSubpasses;
583 			0,											// uint32_t                          dependencyCount;
584 			DE_NULL										// const VkSubpassDependency*        pDependencies
585 		};
586 
587 		renderPass = createRenderPass(vk, device, &renderPassInfo);
588 
589 		const VkFramebufferCreateInfo framebufferInfo =
590 		{
591 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType             sType;
592 			DE_NULL,									// const void*                 pNext;
593 			0,											// VkFramebufferCreateFlags    flags;
594 			renderPass.get(),							// VkRenderPass                renderPass;
595 			0,											// uint32_t                    attachmentCount;
596 			DE_NULL,									// const VkImageView*          pAttachments;
597 			1,											// uint32_t                    width;
598 			1,											// uint32_t                    height;
599 			1,											// uint32_t                    layers;
600 		};
601 
602 		fbo = createFramebuffer(vk, device, &framebufferInfo);
603 
604 		vertexModule   = createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u);
605 		fragmentModule = createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u);
606 
607 		const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
608 		{
609 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
610 			DE_NULL,														// const void*								pNext;
611 			(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags	flags;
612 			0,																// uint32_t									vertexBindingDescriptionCount;
613 			DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
614 			0,																// uint32_t									vertexAttributeDescriptionCount;
615 			DE_NULL,														// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
616 		};
617 
618 		const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
619 		{
620 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
621 			DE_NULL,														// const void*								pNext;
622 			(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
623 			VK_PRIMITIVE_TOPOLOGY_POINT_LIST,								// VkPrimitiveTopology						topology;
624 			VK_FALSE,														// VkBool32									primitiveRestartEnable;
625 		};
626 
627 		std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
628 
629 		{
630 			const VkPipelineShaderStageCreateInfo createInfo =
631 			{
632 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
633 				DE_NULL,												// const void*							pNext;
634 				(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
635 				VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage;
636 				vertexModule.get(),										// VkShaderModule						module;
637 				"main",													// const char*							pName;
638 				DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
639 			};
640 
641 			shaderStages.push_back(createInfo);
642 		}
643 
644 		{
645 			const VkPipelineShaderStageCreateInfo createInfo =
646 			{
647 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
648 				DE_NULL,												// const void*							pNext;
649 				(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
650 				VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits				stage;
651 				fragmentModule.get(),									// VkShaderModule						module;
652 				"main",													// const char*							pName;
653 				DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
654 			};
655 
656 			shaderStages.push_back(createInfo);
657 		}
658 
659 		VkViewport viewport;
660 
661 		viewport.x			= 0;
662 		viewport.y			= 0;
663 		viewport.width		= 1;
664 		viewport.height		= 1;
665 		viewport.minDepth	= 0.0f;
666 		viewport.maxDepth	= 1.0f;
667 
668 		VkRect2D scissor;
669 
670 		scissor.offset.x		= 0;
671 		scissor.offset.y		= 0;
672 		scissor.extent.width	= 1;
673 		scissor.extent.height	= 1;
674 
675 		const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
676 		{
677 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
678 			DE_NULL,														// const void*							pNext;
679 			(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags	flags;
680 			1u,																// uint32_t								viewportCount;
681 			&viewport,														// const VkViewport*					pViewports;
682 			1u,																// uint32_t								scissorCount;
683 			&scissor,														// const VkRect2D*						pScissors;
684 		};
685 
686 		const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
687 		{
688 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
689 			DE_NULL,													// const void*								pNext;
690 			(VkPipelineRasterizationStateCreateFlags)0,					// VkPipelineRasterizationStateCreateFlags	flags;
691 			VK_FALSE,													// VkBool32									depthClampEnable;
692 			VK_FALSE,													// VkBool32									rasterizerDiscardEnable;
693 			VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode;
694 			VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode;
695 			VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
696 			VK_FALSE,													// VkBool32									depthBiasEnable;
697 			0.0f,														// float									depthBiasConstantFactor;
698 			0.0f,														// float									depthBiasClamp;
699 			0.0f,														// float									depthBiasSlopeFactor;
700 			1.0f,														// float									lineWidth;
701 		};
702 
703 		const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
704 		{
705 
706 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
707 			DE_NULL,													// const void*								pNext;
708 			(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
709 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
710 			VK_FALSE,													// VkBool32									sampleShadingEnable;
711 			1.0f,														// float									minSampleShading;
712 			DE_NULL,													// const VkSampleMask*						pSampleMask;
713 			VK_FALSE,													// VkBool32									alphaToCoverageEnable;
714 			VK_FALSE,													// VkBool32									alphaToOneEnable;
715 		};
716 
717 		const VkStencilOpState						noStencilOp					=
718 		{
719 			VK_STENCIL_OP_KEEP,		// VkStencilOp    failOp
720 			VK_STENCIL_OP_KEEP,		// VkStencilOp    passOp
721 			VK_STENCIL_OP_KEEP,		// VkStencilOp    depthFailOp
722 			VK_COMPARE_OP_NEVER,	// VkCompareOp    compareOp
723 			0,						// deUint32       compareMask
724 			0,						// deUint32       writeMask
725 			0						// deUint32       reference
726 		};
727 
728 		VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
729 		{
730 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
731 			DE_NULL,													// const void*								pNext;
732 			(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
733 			VK_FALSE,													// VkBool32									depthTestEnable;
734 			VK_FALSE,													// VkBool32									depthWriteEnable;
735 			VK_COMPARE_OP_ALWAYS,										// VkCompareOp								depthCompareOp;
736 			VK_FALSE,													// VkBool32									depthBoundsTestEnable;
737 			VK_FALSE,													// VkBool32									stencilTestEnable;
738 			noStencilOp,												// VkStencilOpState							front;
739 			noStencilOp,												// VkStencilOpState							back;
740 			0.0f,														// float									minDepthBounds;
741 			1.0f,														// float									maxDepthBounds;
742 		};
743 
744 		const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
745 		{
746 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
747 			DE_NULL,													// const void*									pNext;
748 			(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
749 			VK_FALSE,													// VkBool32										logicOpEnable;
750 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
751 			0,															// deUint32										attachmentCount;
752 			DE_NULL,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
753 			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
754 		};
755 
756 		const VkGraphicsPipelineCreateInfo	graphicsPipelineInfo =
757 		{
758 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,			// VkStructureType									sType;
759 			DE_NULL,													// const void*										pNext;
760 			(VkPipelineCreateFlags)0,									// VkPipelineCreateFlags							flags;
761 			static_cast<deUint32>(shaderStages.size()),					// deUint32											stageCount;
762 			dataOrNullPtr(shaderStages),								// const VkPipelineShaderStageCreateInfo*			pStages;
763 			&vertexInputStateInfo,										// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
764 			&pipelineInputAssemblyStateInfo,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
765 			DE_NULL,													// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
766 			&pipelineViewportStateInfo,									// const VkPipelineViewportStateCreateInfo*			pViewportState;
767 			&pipelineRasterizationStateInfo,							// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
768 			&pipelineMultisampleStateInfo,								// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
769 			&pipelineDepthStencilStateInfo,								// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
770 			&pipelineColorBlendStateInfo,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
771 			DE_NULL,													// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
772 			pipelineLayout.get(),										// VkPipelineLayout									layout;
773 			renderPass.get(),											// VkRenderPass										renderPass;
774 			0,															// deUint32											subpass;
775 			DE_NULL,													// VkPipeline										basePipelineHandle;
776 			-1,															// deInt32											basePipelineIndex;
777 		};
778 
779 		pipeline = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
780 	}
781 	else if (params.method == MEMORY_DEP_DISPATCH)
782 	{
783 		computeModule = createShaderModule(vk, device, context.getBinaryCollection().get("comp"), 0u);
784 
785 		const VkPipelineShaderStageCreateInfo shaderStageInfo =
786 		{
787 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
788 			DE_NULL,												// const void*							pNext;
789 			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
790 			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
791 			computeModule.get(),									// VkShaderModule						module;
792 			"main",													// const char*							pName;
793 			DE_NULL													// const VkSpecializationInfo*			pSpecializationInfo;
794 		};
795 
796 		const VkComputePipelineCreateInfo computePipelineInfo =
797 		{
798 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType                    sType;
799 			DE_NULL,										// const void*                        pNext;
800 			0u,												// VkPipelineCreateFlags              flags;
801 			shaderStageInfo,								// VkPipelineShaderStageCreateInfo    stage;
802 			pipelineLayout.get(),							// VkPipelineLayout                   layout;
803 			DE_NULL,										// VkPipeline                         basePipelineHandle;
804 			0												// int32_t                            basePipelineIndex;
805 		};
806 
807 		pipeline = createComputePipeline(vk, device, DE_NULL, &computePipelineInfo);
808 	}
809 
810 	deMemcpy(markerMemory->getHostPtr(), &expected[0], static_cast<size_t>(markerBufferSize));
811 	flushMappedMemoryRange(vk, device, markerMemory->getMemory(), markerMemory->getOffset(), VK_WHOLE_SIZE);
812 
813 	const Unique<VkCommandPool>		cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, wd.queueFamilyIdx));
814 	const Unique<VkCommandBuffer>	cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
815 
816 	beginCommandBuffer(vk, *cmdBuffer);
817 
818 	VkDescriptorSet setHandle = *descriptorSet;
819 
820 	std::vector<MemoryDepOwner>	dataOwner(size, MEMORY_DEP_OWNER_NOBODY);
821 
822 	if (params.method == MEMORY_DEP_DRAW)
823 	{
824 		const VkRenderPassBeginInfo beginInfo =
825 		{
826 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType        sType;
827 			DE_NULL,									// const void*            pNext;
828 			renderPass.get(),							// VkRenderPass           renderPass;
829 			fbo.get(),									// VkFramebuffer          framebuffer;
830 			{ { 0, 0, }, { 1, 1 } },					// VkRect2D               renderArea;
831 			0,											// uint32_t               clearValueCount;
832 			DE_NULL										// const VkClearValue*    pClearValues;
833 		};
834 
835 		vk.cmdBeginRenderPass(*cmdBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
836 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
837 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &setHandle, 0, DE_NULL);
838 	}
839 	else if (params.method == MEMORY_DEP_DISPATCH)
840 	{
841 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
842 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &setHandle, 0, DE_NULL);
843 	}
844 
845 	deMemcpy(markerMemory->getHostPtr(), &expected[0], static_cast<size_t>(markerBufferSize));
846 	flushMappedMemoryRange(vk, device, markerMemory->getMemory(), markerMemory->getOffset(), VK_WHOLE_SIZE);
847 
848 	deUint32 writeStages = 0;
849 	deUint32 writeAccess = 0;
850 
851 	for (deUint32 i = 0; i < numIters; ++i)
852 	{
853 		deUint32		slot		= rng.getUint32() % size;
854 		MemoryDepOwner	oldOwner	= dataOwner[slot];
855 		MemoryDepOwner	newOwner	= static_cast<MemoryDepOwner>(1 + (rng.getUint32() % 2));
856 
857 		DE_ASSERT(newOwner == MEMORY_DEP_OWNER_MARKER || newOwner == MEMORY_DEP_OWNER_NON_MARKER);
858 		DE_ASSERT(slot < size);
859 
860 		if ((oldOwner != newOwner && oldOwner != MEMORY_DEP_OWNER_NOBODY) ||
861 			(oldOwner == MEMORY_DEP_OWNER_NON_MARKER && newOwner == MEMORY_DEP_OWNER_NON_MARKER))
862 		{
863 			VkBufferMemoryBarrier memoryDep =
864 			{
865 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,    // VkStructureType    sType;
866 				DE_NULL,                                    // const void*        pNext;
867 				0,                                          // VkAccessFlags      srcAccessMask;
868 				0,                                          // VkAccessFlags      dstAccessMask;
869 				wd.queueFamilyIdx,                          // uint32_t           srcQueueFamilyIndex;
870 				wd.queueFamilyIdx,                          // uint32_t           dstQueueFamilyIndex;
871 				*markerBuffer,                              // VkBuffer           buffer;
872 				sizeof(deUint32) * slot,                    // VkDeviceSize       offset;
873 				sizeof(deUint32)                            // VkDeviceSize       size;
874 			};
875 
876 			VkPipelineStageFlags srcStageMask;
877 			VkPipelineStageFlags dstStageMask;
878 
879 			computeMemoryDepBarrier(params.method, oldOwner, &memoryDep.srcAccessMask, &srcStageMask);
880 			computeMemoryDepBarrier(params.method, newOwner, &memoryDep.dstAccessMask, &dstStageMask);
881 
882 			vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 1, &memoryDep, 0, DE_NULL);
883 		}
884 
885 		const deUint32 value = i;
886 
887 		if (newOwner == MEMORY_DEP_OWNER_MARKER)
888 		{
889 			vk.cmdWriteBufferMarkerAMD(*cmdBuffer, params.base.stage, *markerBuffer, sizeof(deUint32) * slot, value);
890 
891 			writeStages |= params.base.stage;
892 			writeAccess |= VK_ACCESS_TRANSFER_WRITE_BIT;
893 		}
894 		else
895 		{
896 			DE_ASSERT(newOwner == MEMORY_DEP_OWNER_NON_MARKER);
897 
898 			if (params.method == MEMORY_DEP_COPY)
899 			{
900 				vk.cmdUpdateBuffer(*cmdBuffer, *markerBuffer, sizeof(deUint32) * slot, sizeof(deUint32), &value);
901 
902 				writeStages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
903 				writeAccess |= VK_ACCESS_TRANSFER_WRITE_BIT;
904 			}
905 			else if (params.method == MEMORY_DEP_DRAW)
906 			{
907 				const deUint32 pushConst[] = { slot, value };
908 
909 				vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, pushConstantStage, 0, sizeof(pushConst), pushConst);
910 				vk.cmdDraw(*cmdBuffer, 1, 1, i, 0);
911 
912 				writeStages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
913 				writeAccess |= VK_ACCESS_SHADER_WRITE_BIT;
914 			}
915 			else
916 			{
917 				const deUint32 pushConst[] = { slot, value };
918 
919 				vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, pushConstantStage, 0, sizeof(pushConst), pushConst);
920 				vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
921 
922 				writeStages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
923 				writeAccess |= VK_ACCESS_SHADER_WRITE_BIT;
924 			}
925 		}
926 
927 		dataOwner[slot] = newOwner;
928 		expected[slot]  = value;
929 	}
930 
931 	if (params.method == MEMORY_DEP_DRAW)
932 	{
933 		vk.cmdEndRenderPass(*cmdBuffer);
934 	}
935 
936 	const VkMemoryBarrier memoryDep =
937 	{
938 		VK_STRUCTURE_TYPE_MEMORY_BARRIER,
939 		DE_NULL,
940 		writeAccess,
941 		VK_ACCESS_HOST_READ_BIT,
942 	};
943 
944 	vk.cmdPipelineBarrier(*cmdBuffer, writeStages, VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memoryDep, 0, DE_NULL, 0, DE_NULL);
945 
946 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
947 
948 	submitCommandsAndWait(vk, device, wd.queue, *cmdBuffer);
949 
950 	if (!checkMarkerBuffer(vk, device, markerMemory, 0, expected))
951 		return tcu::TestStatus::fail("Some marker values were incorrect");
952 
953 	return tcu::TestStatus::pass("Pass");
954 }
955 
initMemoryDepPrograms(SourceCollections & programCollection,const MemoryDepParams params)956 void initMemoryDepPrograms(SourceCollections& programCollection, const MemoryDepParams params)
957 {
958 	if (params.method == MEMORY_DEP_DRAW)
959 	{
960 		{
961 			std::ostringstream src;
962 
963             src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
964                 << "layout(location = 0) flat out uint offset;\n"
965                 << "out gl_PerVertex { vec4 gl_Position; };\n"
966 				<< "void main() {\n"
967 				<< "	offset = gl_VertexIndex;\n"
968 				<< "	gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
969 				<< "}\n";
970 
971 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
972 		}
973 
974 		{
975 			std::ostringstream src;
976 
977 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
978 				<< "layout(push_constant) uniform Constants { uvec2 params; } pc;\n"
979 				<< "layout(std430, set = 0, binding = 0) buffer Data { uint elems[]; } data;\n"
980 				<< "layout(location = 0) flat in uint offset;\n"
981 				<< "void main() {\n"
982 				<< "	data.elems[pc.params.x] = pc.params.y;\n"
983 				<< "}\n";
984 
985 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
986 		}
987 	}
988 	else if (params.method == MEMORY_DEP_DISPATCH)
989 	{
990 		{
991 			std::ostringstream src;
992 
993 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
994 				<< "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
995 				<< "layout(push_constant) uniform Constants { uvec2 params; } pc;\n"
996 				<< "layout(std430, set = 0, binding = 0) buffer Data { uint elems[]; } data;\n"
997 				<< "void main() {\n"
998 				<< "	data.elems[pc.params.x] = pc.params.y;\n"
999 				<< "}\n";
1000 
1001 			programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1002 		}
1003 	}
1004 }
1005 
checkBufferMarkerSupport(Context & context,BaseTestParams params)1006 void checkBufferMarkerSupport (Context& context, BaseTestParams params)
1007 {
1008 	if (params.useHostPtr)
1009 		context.requireDeviceFunctionality("VK_EXT_external_memory_host");
1010 
1011 	context.requireDeviceFunctionality("VK_AMD_buffer_marker");
1012 }
1013 
checkBufferMarkerSupport(Context & context,MemoryDepParams params)1014 void checkBufferMarkerSupport (Context& context, MemoryDepParams params)
1015 {
1016 	if (params.base.useHostPtr)
1017 		context.requireDeviceFunctionality("VK_EXT_external_memory_host");
1018 
1019 	context.requireDeviceFunctionality("VK_AMD_buffer_marker");
1020 }
1021 
createBufferMarkerTestsInGroup(tcu::TestContext & testCtx)1022 tcu::TestCaseGroup* createBufferMarkerTestsInGroup(tcu::TestContext& testCtx)
1023 {
1024 	tcu::TestCaseGroup* root = (new tcu::TestCaseGroup(testCtx, "buffer_marker", "AMD_buffer_marker Tests"));
1025 
1026 	VkQueueFlagBits queues[] = { VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT };
1027 	const char* queueNames[] = { "graphics", "compute", "transfer" };
1028 
1029 	BaseTestParams base;
1030 	deMemset(&base, 0, sizeof(base));
1031 
1032 	for (size_t queueNdx = 0; queueNdx < DE_LENGTH_OF_ARRAY(queues); ++queueNdx)
1033 	{
1034 		tcu::TestCaseGroup* queueGroup = (new tcu::TestCaseGroup(testCtx, queueNames[queueNdx], "Buffer marker tests for a specific queue family"));
1035 
1036 		const char* memoryNames[] = { "external_host_mem", "default_mem" };
1037 		const bool memoryTypes[] = { true, false };
1038 
1039 		base.testQueue = queues[queueNdx];
1040 
1041 		for (size_t memNdx = 0; memNdx < DE_LENGTH_OF_ARRAY(memoryTypes); ++memNdx)
1042 		{
1043 			tcu::TestCaseGroup* memoryGroup = (new tcu::TestCaseGroup(testCtx, memoryNames[memNdx], "Buffer marker tests for different kinds of backing memory"));
1044 
1045 			base.useHostPtr = memoryTypes[memNdx];
1046 
1047 			VkPipelineStageFlagBits stages[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT };
1048 			const char* stageNames[] = { "top_of_pipe", "bottom_of_pipe" };
1049 
1050 			for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
1051 			{
1052 				tcu::TestCaseGroup* stageGroup = (new tcu::TestCaseGroup(testCtx, stageNames[stageNdx], "Buffer marker tests for a specific pipeline stage"));
1053 
1054 				base.stage = stages[stageNdx];
1055 
1056 				{
1057 					tcu::TestCaseGroup* sequentialGroup = (new tcu::TestCaseGroup(testCtx, "sequential", "Buffer marker tests for sequentially writing"));
1058 
1059 					base.size = 4;
1060 
1061 					addFunctionCase(sequentialGroup, "4", "Writes 4 sequential marker values into a buffer", checkBufferMarkerSupport, bufferMarkerSequential, base);
1062 
1063 					base.size = 64;
1064 
1065 					addFunctionCase(sequentialGroup, "64", "Writes 64 sequential marker values into a buffer", checkBufferMarkerSupport, bufferMarkerSequential, base);
1066 
1067 					base.size = 65536;
1068 
1069 					addFunctionCase(sequentialGroup, "65536", "Writes 65536 sequential marker values into a buffer", checkBufferMarkerSupport, bufferMarkerSequential, base);
1070 
1071 					stageGroup->addChild(sequentialGroup);
1072 				}
1073 
1074 				{
1075 					tcu::TestCaseGroup* overwriteGroup = (new tcu::TestCaseGroup(testCtx, "overwrite", "Buffer marker tests for overwriting values with implicit synchronization"));
1076 
1077 					base.size = 1;
1078 
1079 					addFunctionCase(overwriteGroup, "1", "Randomly overwrites marker values to a 1-size buffer", checkBufferMarkerSupport, bufferMarkerOverwrite, base);
1080 
1081 					base.size = 4;
1082 
1083 					addFunctionCase(overwriteGroup, "4", "Randomly overwrites marker values to a 4-size buffer", checkBufferMarkerSupport, bufferMarkerOverwrite, base);
1084 
1085 					base.size = 64;
1086 
1087 					addFunctionCase(overwriteGroup, "64", "Randomly overwrites markers values to a 64-size buffer", checkBufferMarkerSupport, bufferMarkerOverwrite, base);
1088 
1089 					stageGroup->addChild(overwriteGroup);
1090 				}
1091 
1092 				{
1093 					tcu::TestCaseGroup* memoryDepGroup = (new tcu::TestCaseGroup(testCtx, "memory_dep", "Buffer marker tests for memory dependencies between marker writes and other operations"));
1094 
1095 					MemoryDepParams params;
1096 					deMemset(&params, 0, sizeof(params));
1097 
1098 					params.base		 = base;
1099 					params.base.size = 128;
1100 
1101 					if (params.base.testQueue == VK_QUEUE_GRAPHICS_BIT)
1102 					{
1103 						params.method = MEMORY_DEP_DRAW;
1104 
1105 						addFunctionCaseWithPrograms(memoryDepGroup, "draw", "Test memory dependencies between marker writes and draws", checkBufferMarkerSupport, initMemoryDepPrograms, bufferMarkerMemoryDep, params);
1106 					}
1107 
1108 					if (params.base.testQueue != VK_QUEUE_TRANSFER_BIT)
1109 					{
1110 						params.method = MEMORY_DEP_DISPATCH;
1111 
1112 						addFunctionCaseWithPrograms(memoryDepGroup, "dispatch", "Test memory dependencies between marker writes and compute dispatches", checkBufferMarkerSupport, initMemoryDepPrograms, bufferMarkerMemoryDep, params);
1113 					}
1114 
1115 					params.method = MEMORY_DEP_COPY;
1116 
1117 					addFunctionCaseWithPrograms(memoryDepGroup, "buffer_copy", "Test memory dependencies between marker writes and buffer copies", checkBufferMarkerSupport, initMemoryDepPrograms, bufferMarkerMemoryDep, params);
1118 
1119 					stageGroup->addChild(memoryDepGroup);
1120 				}
1121 
1122 				memoryGroup->addChild(stageGroup);
1123 			}
1124 
1125 			queueGroup->addChild(memoryGroup);
1126 		}
1127 
1128 		root->addChild(queueGroup);
1129 	}
1130 
1131 	return root;
1132 }
1133 
1134 } // anonymous ns
1135 
createBufferMarkerTests(tcu::TestContext & testCtx)1136 tcu::TestCaseGroup* createBufferMarkerTests (tcu::TestContext& testCtx)
1137 {
1138 	return createBufferMarkerTestsInGroup(testCtx);
1139 }
1140 
1141 } // api
1142 } // vkt
1143