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