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