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