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