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