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