1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Synchronization tests for resources shared with DX11 keyed mutex
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationWin32KeyedMutexTests.hpp"
25
26 #include "vkDeviceUtil.hpp"
27 #include "vkPlatform.hpp"
28 #include "vkCmdUtil.hpp"
29
30 #include "vktTestCaseUtil.hpp"
31
32 #include "vktSynchronizationUtil.hpp"
33 #include "vktSynchronizationOperation.hpp"
34 #include "vktSynchronizationOperationTestData.hpp"
35 #include "vktExternalMemoryUtil.hpp"
36
37 #include "tcuResultCollector.hpp"
38 #include "tcuTestLog.hpp"
39
40 #if (DE_OS == DE_OS_WIN32)
41 # define WIN32_LEAN_AND_MEAN
42 # define NOMINMAX
43 # include <windows.h>
44 # include <aclapi.h>
45 # include "VersionHelpers.h"
46 # include "d3d11_2.h"
47 # include "d3dcompiler.h"
48
49 typedef HRESULT (WINAPI * LPD3DX11COMPILEFROMMEMORY)(LPCSTR,
50 SIZE_T,
51 LPCSTR,
52 CONST D3D10_SHADER_MACRO*,
53 LPD3D10INCLUDE,
54 LPCSTR,
55 LPCSTR,
56 UINT,
57 UINT,
58 void*, /* ID3DX11ThreadPump */
59 ID3D10Blob** ,
60 ID3D10Blob** ,
61 HRESULT*);
62 #endif
63
64 using tcu::TestLog;
65 using namespace vkt::ExternalMemoryUtil;
66
67 namespace vkt
68 {
69 using namespace vk;
70 namespace synchronization
71 {
72 namespace
73 {
74
75 static const ResourceDescription s_resourcesWin32KeyedMutex[] =
76 {
77 { RESOURCE_TYPE_BUFFER, tcu::IVec4( 0x4000, 0, 0, 0), vk::VK_IMAGE_TYPE_LAST, vk::VK_FORMAT_UNDEFINED, (vk::VkImageAspectFlags)0 }, // 16 KiB (min max UBO range)
78 { RESOURCE_TYPE_BUFFER, tcu::IVec4(0x40000, 0, 0, 0), vk::VK_IMAGE_TYPE_LAST, vk::VK_FORMAT_UNDEFINED, (vk::VkImageAspectFlags)0 }, // 256 KiB
79
80 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R8_UNORM, vk::VK_IMAGE_ASPECT_COLOR_BIT },
81 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R16_UINT, vk::VK_IMAGE_ASPECT_COLOR_BIT },
82 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_ASPECT_COLOR_BIT },
83 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R16G16B16A16_UINT, vk::VK_IMAGE_ASPECT_COLOR_BIT },
84 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R32G32B32A32_SFLOAT, vk::VK_IMAGE_ASPECT_COLOR_BIT },
85 };
86
87 struct TestConfig
88 {
TestConfigvkt::synchronization::__anon2a7f8c320111::TestConfig89 TestConfig (const ResourceDescription& resource_,
90 OperationName writeOp_,
91 OperationName readOp_,
92 vk::VkExternalMemoryHandleTypeFlagBits memoryHandleTypeBuffer_,
93 vk::VkExternalMemoryHandleTypeFlagBits memoryHandleTypeImage_)
94 : resource (resource_)
95 , writeOp (writeOp_)
96 , readOp (readOp_)
97 , memoryHandleTypeBuffer (memoryHandleTypeBuffer_)
98 , memoryHandleTypeImage (memoryHandleTypeImage_)
99 {
100 }
101
102 const ResourceDescription resource;
103 const OperationName writeOp;
104 const OperationName readOp;
105 const vk::VkExternalMemoryHandleTypeFlagBits memoryHandleTypeBuffer;
106 const vk::VkExternalMemoryHandleTypeFlagBits memoryHandleTypeImage;
107 };
108
checkQueueFlags(vk::VkQueueFlags availableFlags,const vk::VkQueueFlags neededFlags)109 bool checkQueueFlags (vk::VkQueueFlags availableFlags, const vk::VkQueueFlags neededFlags)
110 {
111 if ((availableFlags & (vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT)) != 0)
112 availableFlags |= vk::VK_QUEUE_TRANSFER_BIT;
113
114 return (availableFlags & neededFlags) != 0;
115 }
116
117 class SimpleAllocation : public vk::Allocation
118 {
119 public:
120 SimpleAllocation (const vk::DeviceInterface& vkd,
121 vk::VkDevice device,
122 const vk::VkDeviceMemory memory);
123 ~SimpleAllocation (void);
124
125 private:
126 const vk::DeviceInterface& m_vkd;
127 const vk::VkDevice m_device;
128 };
129
SimpleAllocation(const vk::DeviceInterface & vkd,vk::VkDevice device,const vk::VkDeviceMemory memory)130 SimpleAllocation::SimpleAllocation (const vk::DeviceInterface& vkd,
131 vk::VkDevice device,
132 const vk::VkDeviceMemory memory)
133 : Allocation (memory, 0, DE_NULL)
134 , m_vkd (vkd)
135 , m_device (device)
136 {
137 }
138
~SimpleAllocation(void)139 SimpleAllocation::~SimpleAllocation (void)
140 {
141 m_vkd.freeMemory(m_device, getMemory(), DE_NULL);
142 }
143
createInstance(const vk::PlatformInterface & vkp,deUint32 version)144 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface& vkp, deUint32 version)
145 {
146 try
147 {
148 std::vector<std::string> extensions;
149 if (!isCoreInstanceExtension(version, "VK_KHR_get_physical_device_properties2"))
150 extensions.push_back("VK_KHR_get_physical_device_properties2");
151 if (!isCoreInstanceExtension(version, "VK_KHR_get_physical_device_properties2"))
152 extensions.push_back("VK_KHR_external_memory_capabilities");
153
154 return vk::createDefaultInstance(vkp, version, std::vector<std::string>(), extensions);
155 }
156 catch (const vk::Error& error)
157 {
158 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
159 TCU_THROW(NotSupportedError, "Required external memory extensions not supported by the instance");
160 else
161 throw;
162 }
163 }
164
getPhysicalDevice(const vk::InstanceInterface & vki,vk::VkInstance instance,const tcu::CommandLine & cmdLine)165 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki,
166 vk::VkInstance instance,
167 const tcu::CommandLine& cmdLine)
168 {
169 return vk::chooseDevice(vki, instance, cmdLine);
170 }
171
createDevice(const deUint32 apiVersion,const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice)172 vk::Move<vk::VkDevice> createDevice (const deUint32 apiVersion,
173 const vk::PlatformInterface& vkp,
174 vk::VkInstance instance,
175 const vk::InstanceInterface& vki,
176 vk::VkPhysicalDevice physicalDevice)
177 {
178 const float priority = 0.0f;
179 const std::vector<vk::VkQueueFamilyProperties> queueFamilyProperties = vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
180 std::vector<deUint32> queueFamilyIndices (queueFamilyProperties.size(), 0xFFFFFFFFu);
181 std::vector<const char*> extensions;
182
183 if (!isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
184 extensions.push_back("VK_KHR_external_memory");
185 if (!isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
186 extensions.push_back("VK_KHR_dedicated_allocation");
187 if (!isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
188 extensions.push_back("VK_KHR_get_memory_requirements2");
189
190 extensions.push_back("VK_KHR_external_memory_win32");
191 extensions.push_back("VK_KHR_win32_keyed_mutex");
192
193 try
194 {
195 std::vector<vk::VkDeviceQueueCreateInfo> queues;
196
197 for (size_t ndx = 0; ndx < queueFamilyProperties.size(); ndx++)
198 {
199 const vk::VkDeviceQueueCreateInfo createInfo =
200 {
201 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
202 DE_NULL,
203 0u,
204
205 (deUint32)ndx,
206 1u,
207 &priority
208 };
209
210 queues.push_back(createInfo);
211 }
212
213 const vk::VkDeviceCreateInfo createInfo =
214 {
215 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
216 DE_NULL,
217 0u,
218
219 (deUint32)queues.size(),
220 &queues[0],
221
222 0u,
223 DE_NULL,
224
225 (deUint32)extensions.size(),
226 extensions.empty() ? DE_NULL : &extensions[0],
227 0u
228 };
229
230 return vk::createDevice(vkp, instance, vki, physicalDevice, &createInfo);
231 }
232 catch (const vk::Error& error)
233 {
234 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
235 TCU_THROW(NotSupportedError, "Required extensions not supported");
236 else
237 throw;
238 }
239 }
240
chooseMemoryType(deUint32 bits)241 deUint32 chooseMemoryType (deUint32 bits)
242 {
243 DE_ASSERT(bits != 0);
244
245 for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++)
246 {
247 if ((bits & (1u << memoryTypeIndex)) != 0)
248 return memoryTypeIndex;
249 }
250
251 DE_FATAL("No supported memory types");
252 return -1;
253 }
254
importMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,NativeHandle & handle,bool requiresDedicated,vk::VkBuffer buffer,vk::VkImage image)255 vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface& vkd,
256 vk::VkDevice device,
257 const vk::VkMemoryRequirements& requirements,
258 vk::VkExternalMemoryHandleTypeFlagBits externalType,
259 NativeHandle& handle,
260 bool requiresDedicated,
261 vk::VkBuffer buffer,
262 vk::VkImage image)
263 {
264 const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo =
265 {
266 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
267 DE_NULL,
268 image,
269 buffer,
270 };
271 const vk::VkImportMemoryWin32HandleInfoKHR importInfo =
272 {
273 vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
274 (requiresDedicated) ? &dedicatedInfo : DE_NULL,
275 externalType,
276 handle.getWin32Handle(),
277 NULL
278 };
279
280 const vk::VkMemoryAllocateInfo info =
281 {
282 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
283 &importInfo,
284 requirements.size,
285 chooseMemoryType(requirements.memoryTypeBits)
286 };
287
288 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info));
289
290 handle.disown();
291
292 return memory;
293 }
294
importAndBindMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBuffer buffer,NativeHandle & nativeHandle,vk::VkExternalMemoryHandleTypeFlagBits externalType)295 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
296 vk::VkDevice device,
297 vk::VkBuffer buffer,
298 NativeHandle& nativeHandle,
299 vk::VkExternalMemoryHandleTypeFlagBits externalType)
300 {
301 const vk::VkBufferMemoryRequirementsInfo2 requirementsInfo =
302 {
303 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
304 DE_NULL,
305 buffer,
306 };
307 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
308 {
309 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
310 DE_NULL,
311 VK_FALSE,
312 VK_FALSE,
313 };
314 vk::VkMemoryRequirements2 requirements =
315 {
316 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
317 &dedicatedRequirements,
318 { 0u, 0u, 0u, },
319 };
320 vkd.getBufferMemoryRequirements2(device, &requirementsInfo, &requirements);
321
322 vk::Move<vk::VkDeviceMemory> memory = importMemory(vkd, device, requirements.memoryRequirements, externalType, nativeHandle, !!dedicatedRequirements.requiresDedicatedAllocation, buffer, DE_NULL);
323 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
324
325 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
326 }
327
importAndBindMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,NativeHandle & nativeHandle,vk::VkExternalMemoryHandleTypeFlagBits externalType)328 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
329 vk::VkDevice device,
330 vk::VkImage image,
331 NativeHandle& nativeHandle,
332 vk::VkExternalMemoryHandleTypeFlagBits externalType)
333 {
334 const vk::VkImageMemoryRequirementsInfo2 requirementsInfo =
335 {
336 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
337 DE_NULL,
338 image,
339 };
340 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
341 {
342 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
343 DE_NULL,
344 VK_FALSE,
345 VK_FALSE,
346 };
347 vk::VkMemoryRequirements2 requirements =
348 {
349 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
350 &dedicatedRequirements,
351 { 0u, 0u, 0u, },
352 };
353 vkd.getImageMemoryRequirements2(device, &requirementsInfo, &requirements);
354
355 vk::Move<vk::VkDeviceMemory> memory = importMemory(vkd, device, requirements.memoryRequirements, externalType, nativeHandle, !!dedicatedRequirements.requiresDedicatedAllocation, DE_NULL, image);
356 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
357
358 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
359 }
360
importResource(const vk::DeviceInterface & vkd,vk::VkDevice device,const ResourceDescription & resourceDesc,const std::vector<deUint32> & queueFamilyIndices,const OperationSupport & readOp,const OperationSupport & writeOp,NativeHandle & nativeHandle,vk::VkExternalMemoryHandleTypeFlagBits externalType)361 de::MovePtr<Resource> importResource (const vk::DeviceInterface& vkd,
362 vk::VkDevice device,
363 const ResourceDescription& resourceDesc,
364 const std::vector<deUint32>& queueFamilyIndices,
365 const OperationSupport& readOp,
366 const OperationSupport& writeOp,
367 NativeHandle& nativeHandle,
368 vk::VkExternalMemoryHandleTypeFlagBits externalType)
369 {
370 if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
371 {
372 const vk::VkExtent3D extent =
373 {
374 (deUint32)resourceDesc.size.x(),
375 de::max(1u, (deUint32)resourceDesc.size.y()),
376 de::max(1u, (deUint32)resourceDesc.size.z())
377 };
378 const vk::VkImageSubresourceRange subresourceRange =
379 {
380 resourceDesc.imageAspect,
381 0u,
382 1u,
383 0u,
384 1u
385 };
386 const vk::VkImageSubresourceLayers subresourceLayers =
387 {
388 resourceDesc.imageAspect,
389 0u,
390 0u,
391 1u
392 };
393 const vk::VkExternalMemoryImageCreateInfo externalInfo =
394 {
395 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
396 DE_NULL,
397 (vk::VkExternalMemoryHandleTypeFlags)externalType
398 };
399 const vk::VkImageCreateInfo createInfo =
400 {
401 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
402 &externalInfo,
403 0u,
404
405 resourceDesc.imageType,
406 resourceDesc.imageFormat,
407 extent,
408 1u,
409 1u,
410 vk::VK_SAMPLE_COUNT_1_BIT,
411 vk::VK_IMAGE_TILING_OPTIMAL,
412 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
413 vk::VK_SHARING_MODE_EXCLUSIVE,
414
415 (deUint32)queueFamilyIndices.size(),
416 &queueFamilyIndices[0],
417 vk::VK_IMAGE_LAYOUT_UNDEFINED
418 };
419
420 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo);
421 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *image, nativeHandle, externalType);
422
423 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
424 }
425 else
426 {
427 const vk::VkDeviceSize offset = 0u;
428 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
429 const vk::VkBufferUsageFlags usage = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags();
430 const vk::VkExternalMemoryBufferCreateInfo externalInfo =
431 {
432 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
433 DE_NULL,
434 (vk::VkExternalMemoryHandleTypeFlags)externalType
435 };
436 const vk::VkBufferCreateInfo createInfo =
437 {
438 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
439 &externalInfo,
440 0u,
441
442 size,
443 usage,
444 vk::VK_SHARING_MODE_EXCLUSIVE,
445 (deUint32)queueFamilyIndices.size(),
446 &queueFamilyIndices[0]
447 };
448 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo);
449 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *buffer, nativeHandle, externalType);
450
451 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
452 }
453 }
454
recordWriteBarrier(const vk::DeviceInterface & vkd,vk::VkCommandBuffer commandBuffer,const Resource & resource,const SyncInfo & writeSync,deUint32 writeQueueFamilyIndex,const SyncInfo & readSync)455 void recordWriteBarrier (const vk::DeviceInterface& vkd,
456 vk::VkCommandBuffer commandBuffer,
457 const Resource& resource,
458 const SyncInfo& writeSync,
459 deUint32 writeQueueFamilyIndex,
460 const SyncInfo& readSync)
461 {
462 const vk::VkPipelineStageFlags srcStageMask = writeSync.stageMask;
463 const vk::VkAccessFlags srcAccessMask = writeSync.accessMask;
464
465 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
466 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
467
468 const vk::VkDependencyFlags dependencyFlags = 0;
469
470 if (resource.getType() == RESOURCE_TYPE_IMAGE)
471 {
472 const vk::VkImageMemoryBarrier barrier =
473 {
474 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
475 DE_NULL,
476
477 srcAccessMask,
478 dstAccessMask,
479
480 writeSync.imageLayout,
481 readSync.imageLayout,
482
483 writeQueueFamilyIndex,
484 VK_QUEUE_FAMILY_EXTERNAL,
485
486 resource.getImage().handle,
487 resource.getImage().subresourceRange
488 };
489
490 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
491 }
492 else
493 {
494 const vk::VkBufferMemoryBarrier barrier =
495 {
496 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
497 DE_NULL,
498
499 srcAccessMask,
500 dstAccessMask,
501
502 writeQueueFamilyIndex,
503 VK_QUEUE_FAMILY_EXTERNAL,
504
505 resource.getBuffer().handle,
506 0u,
507 VK_WHOLE_SIZE
508 };
509
510 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
511 }
512 }
513
recordReadBarrier(const vk::DeviceInterface & vkd,vk::VkCommandBuffer commandBuffer,const Resource & resource,const SyncInfo & writeSync,const SyncInfo & readSync,deUint32 readQueueFamilyIndex)514 void recordReadBarrier (const vk::DeviceInterface& vkd,
515 vk::VkCommandBuffer commandBuffer,
516 const Resource& resource,
517 const SyncInfo& writeSync,
518 const SyncInfo& readSync,
519 deUint32 readQueueFamilyIndex)
520 {
521 const vk::VkPipelineStageFlags srcStageMask = readSync.stageMask;
522 const vk::VkAccessFlags srcAccessMask = readSync.accessMask;
523
524 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
525 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
526
527 const vk::VkDependencyFlags dependencyFlags = 0;
528
529 if (resource.getType() == RESOURCE_TYPE_IMAGE)
530 {
531 const vk::VkImageMemoryBarrier barrier =
532 {
533 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
534 DE_NULL,
535
536 srcAccessMask,
537 dstAccessMask,
538
539 writeSync.imageLayout,
540 readSync.imageLayout,
541
542 VK_QUEUE_FAMILY_EXTERNAL,
543 readQueueFamilyIndex,
544
545 resource.getImage().handle,
546 resource.getImage().subresourceRange
547 };
548
549 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
550 }
551 else
552 {
553 const vk::VkBufferMemoryBarrier barrier =
554 {
555 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
556 DE_NULL,
557
558 srcAccessMask,
559 dstAccessMask,
560
561 VK_QUEUE_FAMILY_EXTERNAL,
562 readQueueFamilyIndex,
563
564 resource.getBuffer().handle,
565 0u,
566 VK_WHOLE_SIZE
567 };
568
569 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
570 }
571 }
572
getFamilyIndices(const std::vector<vk::VkQueueFamilyProperties> & properties)573 std::vector<deUint32> getFamilyIndices (const std::vector<vk::VkQueueFamilyProperties>& properties)
574 {
575 std::vector<deUint32> indices (properties.size(), 0);
576
577 for (deUint32 ndx = 0; ndx < properties.size(); ndx++)
578 indices[ndx] = ndx;
579
580 return indices;
581 }
582
583 class DX11Operation
584 {
585 public:
586 enum Buffer
587 {
588 BUFFER_VK_WRITE,
589 BUFFER_VK_READ,
590 BUFFER_COUNT,
591 };
592
593 enum KeyedMutex
594 {
595 KEYED_MUTEX_INIT = 0,
596 KEYED_MUTEX_VK_WRITE = 1,
597 KEYED_MUTEX_DX_COPY = 2,
598 KEYED_MUTEX_VK_VERIFY = 3,
599 KEYED_MUTEX_DONE = 4,
600 };
601
602 #if (DE_OS == DE_OS_WIN32)
DX11Operation(const ResourceDescription & resourceDesc,vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType,ID3D11Device * pDevice,ID3D11DeviceContext * pContext,LPD3DX11COMPILEFROMMEMORY fnD3DX11CompileFromMemory,pD3DCompile fnD3DCompile)603 DX11Operation (const ResourceDescription& resourceDesc,
604 vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType,
605 ID3D11Device* pDevice,
606 ID3D11DeviceContext* pContext,
607 LPD3DX11COMPILEFROMMEMORY fnD3DX11CompileFromMemory,
608 pD3DCompile fnD3DCompile)
609 : m_resourceDesc (resourceDesc)
610
611 , m_pDevice (pDevice)
612 , m_pContext (pContext)
613 , m_fnD3DX11CompileFromMemory (fnD3DX11CompileFromMemory)
614 , m_fnD3DCompile (fnD3DCompile)
615
616 , m_pRenderTargetView (0)
617 , m_pVertexShader (0)
618 , m_pPixelShader (0)
619 , m_pVertexBuffer (0)
620 , m_pTextureRV (0)
621 , m_pSamplerLinear (0)
622 , m_numFrames (0)
623 {
624 HRESULT hr;
625
626 if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
627 memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT)
628
629 m_isMemNtHandle = true;
630 else
631 m_isMemNtHandle = false;
632
633 m_securityAttributes.lpSecurityDescriptor = 0;
634
635 for (UINT i = 0; i < BUFFER_COUNT; i++)
636 {
637 m_pTexture[i] = NULL;
638 m_pBuffer[i] = NULL;
639 m_keyedMutex[i] = NULL;
640 }
641
642 if (m_resourceDesc.type == RESOURCE_TYPE_BUFFER)
643 {
644 // SHARED_NTHANDLE is not supported with CreateBuffer().
645 TCU_CHECK_INTERNAL(!m_isMemNtHandle);
646
647 D3D11_BUFFER_DESC descBuf = { };
648 descBuf.ByteWidth = (UINT)m_resourceDesc.size.x();
649 descBuf.Usage = D3D11_USAGE_DEFAULT;
650 descBuf.BindFlags = 0;
651 descBuf.CPUAccessFlags = 0;
652 descBuf.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
653 descBuf.StructureByteStride = 0;
654
655 for (UINT i = 0; i < BUFFER_COUNT; ++i)
656 {
657 hr = m_pDevice->CreateBuffer(&descBuf, NULL, &m_pBuffer[i]);
658 if (FAILED(hr))
659 TCU_FAIL("Failed to create a buffer");
660
661 m_sharedMemHandle[i] = 0;
662
663 IDXGIResource* tempResource = NULL;
664 hr = m_pBuffer[i]->QueryInterface(__uuidof(IDXGIResource), (void**)&tempResource);
665 if (FAILED(hr))
666 TCU_FAIL("Query interface of IDXGIResource failed");
667 hr = tempResource->GetSharedHandle(&m_sharedMemHandle[i]);
668 tempResource->Release();
669 if (FAILED(hr))
670 TCU_FAIL("Failed to get DX shared handle");
671
672 hr = m_pBuffer[i]->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&m_keyedMutex[i]);
673 if (FAILED(hr))
674 TCU_FAIL("Query interface of IDXGIKeyedMutex failed");
675
676 // Take ownership of the lock.
677 m_keyedMutex[i]->AcquireSync(KEYED_MUTEX_INIT, INFINITE);
678 }
679
680 // Release the buffer write lock for Vulkan to write into.
681 m_keyedMutex[BUFFER_VK_WRITE]->ReleaseSync(KEYED_MUTEX_VK_WRITE);
682
683 m_sharedMemSize = descBuf.ByteWidth;
684 m_sharedMemOffset = 0;
685 }
686 else
687 {
688 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
689
690 for (UINT i = 0; i < BUFFER_COUNT; ++i)
691 {
692 D3D11_TEXTURE2D_DESC descColor = { };
693 descColor.Width = m_resourceDesc.size.x();
694 descColor.Height = m_resourceDesc.size.y();
695 descColor.MipLevels = 1;
696 descColor.ArraySize = 1;
697 descColor.Format = getDxgiFormat(m_resourceDesc.imageFormat);
698 descColor.SampleDesc.Count = 1;
699 descColor.SampleDesc.Quality = 0;
700 descColor.Usage = D3D11_USAGE_DEFAULT;
701 descColor.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
702 descColor.CPUAccessFlags = 0;
703
704 if (m_isMemNtHandle)
705 descColor.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
706 else
707 descColor.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
708
709 hr = m_pDevice->CreateTexture2D(&descColor, NULL, &m_pTexture[i]);
710 if (FAILED(hr))
711 TCU_FAIL("Unable to create DX11 texture");
712
713 m_sharedMemHandle[i] = 0;
714
715 if (m_isMemNtHandle)
716 {
717 IDXGIResource1* tempResource1 = NULL;
718 hr = m_pTexture[i]->QueryInterface(__uuidof(IDXGIResource1), (void**)&tempResource1);
719 if (FAILED(hr))
720 TCU_FAIL("Unable to query IDXGIResource1 interface");
721
722 hr = tempResource1->CreateSharedHandle(getSecurityAttributes(), DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, /*lpName*/NULL, &m_sharedMemHandle[i]);
723 tempResource1->Release();
724 if (FAILED(hr))
725 TCU_FAIL("Enable to get DX shared handle");
726 }
727 else
728 {
729 IDXGIResource* tempResource = NULL;
730 hr = m_pTexture[i]->QueryInterface(__uuidof(IDXGIResource), (void**)&tempResource);
731 if (FAILED(hr))
732 TCU_FAIL("Query interface of IDXGIResource failed");
733 hr = tempResource->GetSharedHandle(&m_sharedMemHandle[i]);
734 tempResource->Release();
735 if (FAILED(hr))
736 TCU_FAIL("Failed to get DX shared handle");
737 }
738
739 hr = m_pTexture[i]->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&m_keyedMutex[i]);
740 if (FAILED(hr))
741 TCU_FAIL("Unable to query DX11 keyed mutex interface");
742
743 // Take ownership of the lock.
744 m_keyedMutex[i]->AcquireSync(KEYED_MUTEX_INIT, INFINITE);
745 }
746
747 m_sharedMemSize = 0;
748 m_sharedMemOffset = 0;
749
750 hr = m_pDevice->CreateRenderTargetView(m_pTexture[BUFFER_VK_READ], NULL, &m_pRenderTargetView);
751 if (FAILED(hr))
752 TCU_FAIL("Unable to create DX11 render target view");
753
754 m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);
755
756 // Setup the viewport
757 D3D11_VIEWPORT vp;
758 vp.Width = (FLOAT)m_resourceDesc.size.x();
759 vp.Height = (FLOAT)m_resourceDesc.size.y();
760 vp.MinDepth = 0.0f;
761 vp.MaxDepth = 1.0f;
762 vp.TopLeftX = 0;
763 vp.TopLeftY = 0;
764 m_pContext->RSSetViewports(1, &vp);
765
766 // Compile the vertex shader
767 LPCSTR shader =
768 "Texture2D txDiffuse : register(t0);\n"
769 "SamplerState samLinear : register(s0);\n"
770 "struct VS_INPUT\n"
771 "{\n"
772 " float4 Pos : POSITION;\n"
773 " float2 Tex : TEXCOORD0;\n"
774 "};\n"
775 "struct PS_INPUT\n"
776 "{\n"
777 " float4 Pos : SV_POSITION;\n"
778 " float2 Tex : TEXCOORD0;\n"
779 "};\n"
780 "PS_INPUT VS(VS_INPUT input)\n"
781 "{\n"
782 " PS_INPUT output = (PS_INPUT)0;\n"
783 " output.Pos = input.Pos;\n"
784 " output.Tex = input.Tex;\n"
785 "\n"
786 " return output;\n"
787 "}\n"
788 "float4 PS(PS_INPUT input) : SV_Target\n"
789 "{\n"
790 " return txDiffuse.Sample(samLinear, input.Tex);\n"
791 "}\n";
792
793 // Define the input layout
794 D3D11_INPUT_ELEMENT_DESC layout[] =
795 {
796 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
797 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
798 };
799
800 createShaders(shader, "VS", "vs_4_0", ARRAYSIZE(layout), layout, &m_pVertexShader, "PS", "ps_4_0", &m_pPixelShader);
801
802 struct SimpleVertex
803 {
804 float Pos[3];
805 float Tex[2];
806 };
807
808 SimpleVertex vertices[] =
809 {
810 { { -1.f, -1.f, 0.0f }, { 0.0f, 1.0f } },
811 { { -1.f, 1.f, 0.0f }, { 0.0f, 0.0f } },
812 { { 1.f, -1.f, 0.0f }, { 1.0f, 1.0f } },
813 { { 1.f, 1.f, 0.0f }, { 1.0f, 0.0f } },
814 };
815
816 D3D11_BUFFER_DESC bd = { };
817 bd.Usage = D3D11_USAGE_DEFAULT;
818 bd.ByteWidth = sizeof (vertices);
819 bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
820 bd.CPUAccessFlags = 0;
821 D3D11_SUBRESOURCE_DATA InitData = { };
822 InitData.pSysMem = vertices;
823 hr = m_pDevice->CreateBuffer(&bd, &InitData, &m_pVertexBuffer);
824 if (FAILED(hr))
825 TCU_FAIL("Failed to create DX11 vertex buffer");
826
827 // Set vertex buffer
828 UINT stride = sizeof (SimpleVertex);
829 UINT offset = 0;
830 m_pContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);
831
832 // Set primitive topology
833 m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
834
835 m_pTextureRV = NULL;
836
837 D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = { };
838 SRVDesc.Format = getDxgiFormat(m_resourceDesc.imageFormat);
839 SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
840 SRVDesc.Texture2D.MipLevels = 1;
841
842 hr = m_pDevice->CreateShaderResourceView(m_pTexture[BUFFER_VK_WRITE], &SRVDesc, &m_pTextureRV);
843 if (FAILED(hr))
844 TCU_FAIL("Failed to create DX11 resource view");
845
846 // Create the sample state
847 D3D11_SAMPLER_DESC sampDesc = { };
848 sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
849 sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
850 sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
851 sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
852 sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
853 sampDesc.MinLOD = 0;
854 sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
855 hr = m_pDevice->CreateSamplerState(&sampDesc, &m_pSamplerLinear);
856 if (FAILED(hr))
857 TCU_FAIL("Failed to create DX11 sampler state");
858
859 // Release the lock for VK to write into the texture.
860 m_keyedMutex[BUFFER_VK_WRITE]->ReleaseSync(KEYED_MUTEX_VK_WRITE);
861 }
862 }
863
~DX11Operation()864 ~DX11Operation ()
865 {
866 cleanup();
867 }
868 #endif // #if (DE_OS == DE_OS_WIN32)
869
getNativeHandle(Buffer buffer)870 NativeHandle getNativeHandle (Buffer buffer)
871 {
872 #if (DE_OS == DE_OS_WIN32)
873 return NativeHandle((m_isMemNtHandle) ? NativeHandle::WIN32HANDLETYPE_NT : NativeHandle::WIN32HANDLETYPE_KMT, vk::pt::Win32Handle(m_sharedMemHandle[buffer]));
874 #else
875 DE_UNREF(buffer);
876 return NativeHandle();
877 #endif
878 }
879
copyMemory()880 void copyMemory ()
881 {
882 #if (DE_OS == DE_OS_WIN32)
883 m_keyedMutex[BUFFER_VK_WRITE]->AcquireSync(KEYED_MUTEX_DX_COPY, INFINITE);
884
885 if (m_resourceDesc.type == RESOURCE_TYPE_BUFFER) {
886 m_pContext->CopySubresourceRegion(m_pBuffer[BUFFER_VK_READ], 0, 0, 0, 0, m_pBuffer[BUFFER_VK_WRITE], 0, NULL);
887 } else {
888 m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);
889
890 const FLOAT gray[] = { 0.f, 0.f, 1.f, 1.f };
891 m_pContext->ClearRenderTargetView(m_pRenderTargetView, gray);
892
893 m_pContext->VSSetShader(m_pVertexShader, NULL, 0);
894 m_pContext->PSSetShader(m_pPixelShader, NULL, 0);
895 m_pContext->PSSetShaderResources(0, 1, &m_pTextureRV);
896 m_pContext->PSSetSamplers(0, 1, &m_pSamplerLinear);
897 m_pContext->Draw(4, 0);
898 }
899
900 m_keyedMutex[BUFFER_VK_WRITE]->ReleaseSync(KEYED_MUTEX_DONE);
901 m_keyedMutex[BUFFER_VK_READ]->ReleaseSync(KEYED_MUTEX_VK_VERIFY);
902 #endif // #if (DE_OS == DE_OS_WIN32)
903 }
904
905 #if (DE_OS == DE_OS_WIN32)
d3dx11CompileShader(const char * shaderCode,const char * entryPoint,const char * shaderModel,ID3D10Blob ** ppBlobOut)906 void d3dx11CompileShader (const char* shaderCode, const char * entryPoint, const char* shaderModel, ID3D10Blob** ppBlobOut)
907 {
908 HRESULT hr;
909
910 ID3D10Blob* pErrorBlob;
911 hr = m_fnD3DX11CompileFromMemory (shaderCode,
912 strlen(shaderCode),
913 "Memory",
914 NULL,
915 NULL,
916 entryPoint,
917 shaderModel,
918 0,
919 0,
920 NULL,
921 ppBlobOut,
922 &pErrorBlob,
923 NULL);
924 if (pErrorBlob)
925 pErrorBlob->Release();
926
927 if (FAILED(hr))
928 TCU_FAIL("D3DX11CompileFromMemory failed to compile shader");
929 }
930
d3dCompileShader(const char * shaderCode,const char * entryPoint,const char * shaderModel,ID3DBlob ** ppBlobOut)931 void d3dCompileShader (const char* shaderCode, const char * entryPoint, const char* shaderModel, ID3DBlob** ppBlobOut)
932 {
933 HRESULT hr;
934
935 ID3DBlob* pErrorBlob;
936 hr = m_fnD3DCompile (shaderCode,
937 strlen(shaderCode),
938 NULL,
939 NULL,
940 NULL,
941 entryPoint,
942 shaderModel,
943 0,
944 0,
945 ppBlobOut,
946 &pErrorBlob);
947 if (pErrorBlob)
948 pErrorBlob->Release();
949
950 if (FAILED(hr))
951 TCU_FAIL("D3DCompile failed to compile shader");
952 }
953
createShaders(const char * shaderSrc,const char * vsEntryPoint,const char * vsShaderModel,UINT numLayoutDesc,D3D11_INPUT_ELEMENT_DESC * pLayoutDesc,ID3D11VertexShader ** pVertexShader,const char * psEntryPoint,const char * psShaderModel,ID3D11PixelShader ** pPixelShader)954 void createShaders (const char* shaderSrc,
955 const char* vsEntryPoint,
956 const char* vsShaderModel,
957 UINT numLayoutDesc,
958 D3D11_INPUT_ELEMENT_DESC* pLayoutDesc,
959 ID3D11VertexShader** pVertexShader,
960 const char* psEntryPoint,
961 const char* psShaderModel,
962 ID3D11PixelShader** pPixelShader)
963 {
964 HRESULT hr;
965
966 if (m_fnD3DX11CompileFromMemory) {
967 // VS
968 ID3D10Blob* pVSBlob;
969 d3dx11CompileShader(shaderSrc, vsEntryPoint, vsShaderModel, &pVSBlob);
970
971 hr = m_pDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, pVertexShader);
972 if (FAILED(hr))
973 TCU_FAIL("Failed to create DX11 vertex shader");
974
975 ID3D11InputLayout *pVertexLayout;
976 hr = m_pDevice->CreateInputLayout(pLayoutDesc, numLayoutDesc, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &pVertexLayout);
977 if (FAILED(hr))
978 TCU_FAIL("Failed to create vertex input layout");
979
980 m_pContext->IASetInputLayout(pVertexLayout);
981 pVertexLayout->Release();
982 pVSBlob->Release();
983
984 // PS
985 ID3D10Blob* pPSBlob;
986 d3dx11CompileShader(shaderSrc, psEntryPoint, psShaderModel, &pPSBlob);
987
988 hr = m_pDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, pPixelShader);
989 if (FAILED(hr))
990 TCU_FAIL("Failed to create DX11 pixel shader");
991 } else {
992 // VS
993 ID3DBlob* pVSBlob;
994 d3dCompileShader(shaderSrc, vsEntryPoint, vsShaderModel, &pVSBlob);
995
996 hr = m_pDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, pVertexShader);
997 if (FAILED(hr))
998 TCU_FAIL("Failed to create DX11 vertex shader");
999
1000 ID3D11InputLayout *pVertexLayout;
1001 hr = m_pDevice->CreateInputLayout(pLayoutDesc, numLayoutDesc, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &pVertexLayout);
1002 if (FAILED(hr))
1003 TCU_FAIL("Failed to create vertex input layout");
1004
1005 m_pContext->IASetInputLayout(pVertexLayout);
1006 pVertexLayout->Release();
1007 pVSBlob->Release();
1008
1009 // PS
1010 ID3DBlob* pPSBlob;
1011 d3dCompileShader(shaderSrc, psEntryPoint, psShaderModel, &pPSBlob);
1012
1013 hr = m_pDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, pPixelShader);
1014 if (FAILED(hr))
1015 TCU_FAIL("Failed to create DX11 pixel shader");
1016 }
1017 }
1018 #endif // #if (DE_OS == DE_OS_WIN32)
1019
1020 private:
1021 #if (DE_OS == DE_OS_WIN32)
cleanup()1022 void cleanup ()
1023 {
1024 if (m_securityAttributes.lpSecurityDescriptor)
1025 {
1026 freeSecurityDescriptor(m_securityAttributes.lpSecurityDescriptor);
1027 m_securityAttributes.lpSecurityDescriptor = NULL;
1028 }
1029
1030 if (m_pContext)
1031 m_pContext->ClearState();
1032
1033 if (m_pRenderTargetView)
1034 {
1035 m_pRenderTargetView->Release();
1036 m_pRenderTargetView = NULL;
1037 }
1038
1039 if (m_pSamplerLinear)
1040 {
1041 m_pSamplerLinear->Release();
1042 m_pSamplerLinear = NULL;
1043 }
1044
1045 if (m_pTextureRV)
1046 {
1047 m_pTextureRV->Release();
1048 m_pTextureRV = NULL;
1049 }
1050
1051 if (m_pVertexBuffer)
1052 {
1053 m_pVertexBuffer->Release();
1054 m_pVertexBuffer = NULL;
1055 }
1056
1057 if (m_pVertexShader)
1058 {
1059 m_pVertexShader->Release();
1060 m_pVertexShader = NULL;
1061 }
1062
1063 if (m_pPixelShader)
1064 {
1065 m_pPixelShader->Release();
1066 m_pPixelShader = NULL;
1067 }
1068
1069 for (int i = 0; i < BUFFER_COUNT; i++)
1070 {
1071 if (m_keyedMutex[i])
1072 {
1073 m_keyedMutex[i]->AcquireSync(KEYED_MUTEX_DONE, INFINITE);
1074 m_keyedMutex[i]->Release();
1075 m_keyedMutex[i] = NULL;
1076 }
1077
1078 if (m_isMemNtHandle && m_sharedMemHandle[i]) {
1079 CloseHandle(m_sharedMemHandle[i]);
1080 m_sharedMemHandle[i] = 0;
1081 }
1082
1083 if (m_pBuffer[i]) {
1084 m_pBuffer[i]->Release();
1085 m_pBuffer[i] = NULL;
1086 }
1087
1088 if (m_pTexture[i]) {
1089 m_pTexture[i]->Release();
1090 m_pTexture[i] = NULL;
1091 }
1092 }
1093 }
1094
getSecurityDescriptor()1095 static void* getSecurityDescriptor ()
1096 {
1097 PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)deCalloc(SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof (void**));
1098
1099 if (pSD)
1100 {
1101 PSID* ppEveryoneSID = (PSID*)((PBYTE)pSD + SECURITY_DESCRIPTOR_MIN_LENGTH);
1102 PACL* ppACL = (PACL*)((PBYTE)ppEveryoneSID + sizeof(PSID*));
1103
1104 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
1105
1106 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
1107 AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, ppEveryoneSID);
1108
1109 EXPLICIT_ACCESS ea = { };
1110 ea.grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1111 ea.grfAccessMode = SET_ACCESS;
1112 ea.grfInheritance = INHERIT_ONLY;
1113 ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1114 ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1115 ea.Trustee.ptstrName = (LPTSTR)*ppEveryoneSID;
1116
1117 SetEntriesInAcl(1, &ea, NULL, ppACL);
1118
1119 SetSecurityDescriptorDacl(pSD, TRUE, *ppACL, FALSE);
1120 }
1121
1122 return pSD;
1123 }
1124
freeSecurityDescriptor(void * pSD)1125 static void freeSecurityDescriptor (void* pSD)
1126 {
1127 if (pSD)
1128 {
1129 PSID* ppEveryoneSID = (PSID*)((PBYTE)pSD + SECURITY_DESCRIPTOR_MIN_LENGTH);
1130 PACL* ppACL = (PACL*)((PBYTE)ppEveryoneSID + sizeof(PSID*));
1131
1132 if (*ppEveryoneSID)
1133 FreeSid(*ppEveryoneSID);
1134
1135 if (*ppACL)
1136 LocalFree(*ppACL);
1137
1138 deFree(pSD);
1139 }
1140 }
1141
getDxgiFormat(vk::VkFormat format)1142 static DXGI_FORMAT getDxgiFormat (vk::VkFormat format)
1143 {
1144 switch (format)
1145 {
1146 case vk::VK_FORMAT_R8_UNORM:
1147 return DXGI_FORMAT_R8_UNORM;
1148 case vk::VK_FORMAT_R16_UINT:
1149 return DXGI_FORMAT_R16_UINT;
1150 case vk::VK_FORMAT_R8G8B8A8_UNORM:
1151 return DXGI_FORMAT_R8G8B8A8_UNORM;
1152 case vk::VK_FORMAT_R16G16B16A16_UINT:
1153 return DXGI_FORMAT_R16G16B16A16_UINT;
1154 case vk::VK_FORMAT_R32G32B32A32_SFLOAT:
1155 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1156 case vk::VK_FORMAT_D16_UNORM:
1157 return DXGI_FORMAT_D16_UNORM;
1158 case vk::VK_FORMAT_D32_SFLOAT:
1159 return DXGI_FORMAT_D32_FLOAT;
1160 default:
1161 TCU_CHECK_INTERNAL(!"Unsupported DXGI format");
1162 return DXGI_FORMAT_UNKNOWN;
1163 }
1164 }
1165
1166 ResourceDescription m_resourceDesc;
1167
1168 deUint64 m_sharedMemSize;
1169 deUint64 m_sharedMemOffset;
1170 HANDLE m_sharedMemHandle[BUFFER_COUNT];
1171 bool m_isMemNtHandle;
1172
1173 ID3D11Device* m_pDevice;
1174 ID3D11DeviceContext* m_pContext;
1175 LPD3DX11COMPILEFROMMEMORY m_fnD3DX11CompileFromMemory;
1176 pD3DCompile m_fnD3DCompile;
1177
1178 ID3D11RenderTargetView* m_pRenderTargetView;
1179 ID3D11VertexShader* m_pVertexShader;
1180 ID3D11PixelShader* m_pPixelShader;
1181 ID3D11Buffer* m_pVertexBuffer;
1182 ID3D11ShaderResourceView* m_pTextureRV;
1183 ID3D11SamplerState* m_pSamplerLinear;
1184
1185 ID3D11Texture2D* m_pTexture[BUFFER_COUNT];
1186 ID3D11Buffer* m_pBuffer[BUFFER_COUNT];
1187 IDXGIKeyedMutex* m_keyedMutex[BUFFER_COUNT];
1188 UINT m_numFrames;
1189 SECURITY_ATTRIBUTES m_securityAttributes;
1190
getSecurityAttributes()1191 SECURITY_ATTRIBUTES* getSecurityAttributes ()
1192 {
1193 m_securityAttributes.nLength = sizeof (SECURITY_ATTRIBUTES);
1194 m_securityAttributes.bInheritHandle = TRUE;
1195 if (!m_securityAttributes.lpSecurityDescriptor)
1196 m_securityAttributes.lpSecurityDescriptor = getSecurityDescriptor();
1197
1198 return &m_securityAttributes;
1199 }
1200 #endif // #if (DE_OS == DE_OS_WIN32)
1201 };
1202
1203 class DX11OperationSupport
1204 {
1205 public:
DX11OperationSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const ResourceDescription & resourceDesc)1206 DX11OperationSupport (const vk::InstanceInterface& vki,
1207 vk::VkPhysicalDevice physicalDevice,
1208 const ResourceDescription& resourceDesc)
1209 : m_resourceDesc (resourceDesc)
1210 #if (DE_OS == DE_OS_WIN32)
1211 , m_hD3D11Lib (0)
1212 , m_hD3DX11Lib (0)
1213 , m_hD3DCompilerLib (0)
1214 , m_hDxgiLib (0)
1215 , m_fnD3D11CreateDevice (0)
1216 , m_fnD3DX11CompileFromMemory (0)
1217 , m_fnD3DCompile (0)
1218 #endif
1219 {
1220 #if (DE_OS == DE_OS_WIN32)
1221 HRESULT hr;
1222
1223 vk::VkPhysicalDeviceIDProperties propertiesId = { vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES };
1224 vk::VkPhysicalDeviceProperties2 properties = { vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 };
1225
1226 properties.pNext = &propertiesId;
1227
1228 vki.getPhysicalDeviceProperties2(physicalDevice, &properties);
1229 if (!propertiesId.deviceLUIDValid)
1230 TCU_FAIL("Physical device deviceLUIDValid is not valid");
1231
1232
1233 m_hD3D11Lib = LoadLibrary("d3d11.dll");
1234 if (!m_hD3D11Lib)
1235 TCU_FAIL("Failed to load d3d11.dll");
1236
1237
1238 m_fnD3D11CreateDevice = (LPD3D11CREATEDEVICE) GetProcAddress(m_hD3D11Lib, "D3D11CreateDevice");
1239 if (!m_fnD3D11CreateDevice)
1240 TCU_FAIL("Unable to find D3D11CreateDevice() function");
1241
1242 m_hD3DX11Lib = LoadLibrary("d3dx11_42.dll");
1243 if (m_hD3DX11Lib)
1244 m_fnD3DX11CompileFromMemory = (LPD3DX11COMPILEFROMMEMORY) GetProcAddress(m_hD3DX11Lib, "D3DX11CompileFromMemory");
1245 else
1246 {
1247 m_hD3DCompilerLib = LoadLibrary("d3dcompiler_43.dll");
1248 if (!m_hD3DCompilerLib)
1249 m_hD3DCompilerLib = LoadLibrary("d3dcompiler_47.dll");
1250 if (!m_hD3DCompilerLib)
1251 TCU_FAIL("Unable to load DX11 d3dcompiler_43.dll or d3dcompiler_47.dll");
1252
1253 m_fnD3DCompile = (pD3DCompile)GetProcAddress(m_hD3DCompilerLib, "D3DCompile");
1254 if (!m_fnD3DCompile)
1255 TCU_FAIL("Unable to load find D3DCompile");
1256 }
1257
1258 m_hDxgiLib = LoadLibrary("dxgi.dll");
1259 if (!m_hDxgiLib)
1260 TCU_FAIL("Unable to load DX11 dxgi.dll");
1261
1262 typedef HRESULT (WINAPI *LPCREATEDXGIFACTORY1)(REFIID riid, void** ppFactory);
1263 LPCREATEDXGIFACTORY1 CreateDXGIFactory1 = (LPCREATEDXGIFACTORY1)GetProcAddress(m_hDxgiLib, "CreateDXGIFactory1");
1264 if (!CreateDXGIFactory1)
1265 TCU_FAIL("Unable to load find CreateDXGIFactory1");
1266
1267 IDXGIFactory1* pFactory = NULL;
1268 hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), (void**)&pFactory);
1269 if (FAILED(hr))
1270 TCU_FAIL("Unable to create IDXGIFactory interface");
1271
1272 IDXGIAdapter *pAdapter = NULL;
1273 for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
1274 {
1275 DXGI_ADAPTER_DESC desc;
1276 pAdapter->GetDesc(&desc);
1277
1278 if (deMemCmp(&desc.AdapterLuid, propertiesId.deviceLUID, VK_LUID_SIZE_KHR) == 0)
1279 break;
1280 }
1281 pFactory->Release();
1282
1283 D3D_FEATURE_LEVEL fLevel[] = {D3D_FEATURE_LEVEL_11_0};
1284 UINT devflags = D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS | // no separate D3D11 worker thread
1285 #if 0
1286 D3D11_CREATE_DEVICE_DEBUG | // useful for diagnosing DX failures
1287 #endif
1288 D3D11_CREATE_DEVICE_SINGLETHREADED;
1289
1290 hr = m_fnD3D11CreateDevice (pAdapter,
1291 pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE,
1292 NULL,
1293 devflags,
1294 fLevel,
1295 DE_LENGTH_OF_ARRAY(fLevel),
1296 D3D11_SDK_VERSION,
1297 &m_pDevice,
1298 NULL,
1299 &m_pContext);
1300
1301 if (pAdapter) {
1302 pAdapter->Release();
1303 }
1304
1305 if (!m_pDevice)
1306 TCU_FAIL("Failed to created DX11 device");
1307 if (!m_pContext)
1308 TCU_FAIL("Failed to created DX11 context");
1309 #else
1310 DE_UNREF(vki);
1311 DE_UNREF(physicalDevice);
1312 TCU_THROW(NotSupportedError, "OS not supported");
1313 #endif
1314 }
1315
~DX11OperationSupport()1316 ~DX11OperationSupport ()
1317 {
1318 #if (DE_OS == DE_OS_WIN32)
1319 cleanup ();
1320 #endif
1321 }
1322
1323 #if (DE_OS == DE_OS_WIN32)
cleanup()1324 void cleanup ()
1325 {
1326 if (m_pContext) {
1327 m_pContext->Release();
1328 m_pContext = 0;
1329 }
1330
1331 if (m_pDevice) {
1332 m_pDevice->Release();
1333 m_pDevice = 0;
1334 }
1335
1336 if (m_hDxgiLib)
1337 {
1338 FreeLibrary(m_hDxgiLib);
1339 m_hDxgiLib = 0;
1340 }
1341
1342 if (m_hD3DCompilerLib)
1343 {
1344 FreeLibrary(m_hD3DCompilerLib);
1345 m_hD3DCompilerLib = 0;
1346 }
1347
1348 if (m_hD3DX11Lib)
1349 {
1350 FreeLibrary(m_hD3DX11Lib);
1351 m_hD3DX11Lib = 0;
1352 }
1353
1354 if (m_hD3D11Lib)
1355 {
1356 FreeLibrary(m_hD3D11Lib);
1357 m_hD3D11Lib = 0;
1358 }
1359 }
1360
1361 #endif
1362
build(const ResourceDescription & resourceDesc,vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType) const1363 virtual de::MovePtr<DX11Operation> build (const ResourceDescription& resourceDesc, vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType) const
1364 {
1365 #if (DE_OS == DE_OS_WIN32)
1366 return de::MovePtr<DX11Operation>(new DX11Operation(resourceDesc, memoryHandleType, m_pDevice, m_pContext, m_fnD3DX11CompileFromMemory, m_fnD3DCompile));
1367 #else
1368 DE_UNREF(resourceDesc);
1369 DE_UNREF(memoryHandleType);
1370 TCU_THROW(NotSupportedError, "OS not supported");
1371 #endif
1372 }
1373
1374 private:
1375 const ResourceDescription m_resourceDesc;
1376
1377 #if (DE_OS == DE_OS_WIN32)
1378 typedef HRESULT (WINAPI *LPD3D11CREATEDEVICE)(IDXGIAdapter*,
1379 D3D_DRIVER_TYPE,
1380 HMODULE,
1381 UINT,
1382 const D3D_FEATURE_LEVEL*,
1383 UINT,
1384 UINT,
1385 ID3D11Device **,
1386 D3D_FEATURE_LEVEL*,
1387 ID3D11DeviceContext**);
1388
1389 HMODULE m_hD3D11Lib;
1390 HMODULE m_hD3DX11Lib;
1391 HMODULE m_hD3DCompilerLib;
1392 HMODULE m_hDxgiLib;
1393 LPD3D11CREATEDEVICE m_fnD3D11CreateDevice;
1394 LPD3DX11COMPILEFROMMEMORY m_fnD3DX11CompileFromMemory;
1395 pD3DCompile m_fnD3DCompile;
1396 ID3D11Device* m_pDevice;
1397 ID3D11DeviceContext* m_pContext;
1398 #endif
1399 };
1400
1401 class Win32KeyedMutexTestInstance : public TestInstance
1402 {
1403 public:
1404 Win32KeyedMutexTestInstance (Context& context,
1405 TestConfig config);
1406
1407 virtual tcu::TestStatus iterate (void);
1408
1409 private:
1410 const TestConfig m_config;
1411 const de::UniquePtr<OperationSupport> m_supportWriteOp;
1412 const de::UniquePtr<OperationSupport> m_supportReadOp;
1413
1414 const vk::Unique<vk::VkInstance> m_instance;
1415
1416 const vk::InstanceDriver m_vki;
1417 const vk::VkPhysicalDevice m_physicalDevice;
1418 const std::vector<vk::VkQueueFamilyProperties> m_queueFamilies;
1419 const std::vector<deUint32> m_queueFamilyIndices;
1420 const vk::Unique<vk::VkDevice> m_device;
1421 const vk::DeviceDriver m_vkd;
1422
1423 const de::UniquePtr<DX11OperationSupport> m_supportDX11;
1424
1425 const vk::VkExternalMemoryHandleTypeFlagBits m_memoryHandleType;
1426
1427 // \todo Should this be moved to the group same way as in the other tests?
1428 PipelineCacheData m_pipelineCacheData;
1429 tcu::ResultCollector m_resultCollector;
1430 size_t m_queueNdx;
1431
1432 bool m_useDedicatedAllocation;
1433 };
1434
Win32KeyedMutexTestInstance(Context & context,TestConfig config)1435 Win32KeyedMutexTestInstance::Win32KeyedMutexTestInstance (Context& context,
1436 TestConfig config)
1437 : TestInstance (context)
1438 , m_config (config)
1439 , m_supportWriteOp (makeOperationSupport(config.writeOp, config.resource))
1440 , m_supportReadOp (makeOperationSupport(config.readOp, config.resource))
1441
1442 , m_instance (createInstance(context.getPlatformInterface(), context.getUsedApiVersion()))
1443
1444 , m_vki (context.getPlatformInterface(), *m_instance)
1445 , m_physicalDevice (getPhysicalDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
1446 , m_queueFamilies (vk::getPhysicalDeviceQueueFamilyProperties(m_vki, m_physicalDevice))
1447 , m_queueFamilyIndices (getFamilyIndices(m_queueFamilies))
1448 , m_device (createDevice(context.getUsedApiVersion(), context.getPlatformInterface(), *m_instance, m_vki, m_physicalDevice))
1449 , m_vkd (context.getPlatformInterface(), *m_instance, *m_device)
1450
1451 , m_supportDX11 (new DX11OperationSupport(m_vki, m_physicalDevice, config.resource))
1452
1453 , m_memoryHandleType ((m_config.resource.type == RESOURCE_TYPE_IMAGE) ? m_config.memoryHandleTypeImage : m_config.memoryHandleTypeBuffer)
1454
1455 , m_resultCollector (context.getTestContext().getLog())
1456 , m_queueNdx (0)
1457
1458 , m_useDedicatedAllocation (false)
1459 {
1460 #if (DE_OS == DE_OS_WIN32)
1461 TestLog& log = m_context.getTestContext().getLog();
1462
1463 // Check resource support
1464 if (m_config.resource.type == RESOURCE_TYPE_IMAGE)
1465 {
1466 if (m_memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT && !IsWindows8OrGreater())
1467 TCU_THROW(NotSupportedError, "Memory handle type not supported by this OS");
1468
1469 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
1470 {
1471 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
1472 DE_NULL,
1473 m_memoryHandleType
1474 };
1475 const vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo =
1476 {
1477 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
1478 &externalInfo,
1479 m_config.resource.imageFormat,
1480 m_config.resource.imageType,
1481 vk::VK_IMAGE_TILING_OPTIMAL,
1482 m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
1483 0u
1484 };
1485 vk::VkExternalImageFormatProperties externalProperties =
1486 {
1487 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
1488 DE_NULL,
1489 { 0u, 0u, 0u }
1490 };
1491 vk::VkImageFormatProperties2 formatProperties =
1492 {
1493 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
1494 &externalProperties,
1495 {
1496 { 0u, 0u, 0u },
1497 0u,
1498 0u,
1499 0u,
1500 0u,
1501 }
1502 };
1503 const vk::VkResult res = m_vki.getPhysicalDeviceImageFormatProperties2(m_physicalDevice, &imageFormatInfo, &formatProperties);
1504 if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1505 TCU_THROW(NotSupportedError, "Handle type is not compatible");
1506 VK_CHECK(res);
1507
1508 // \todo How to log this nicely?
1509 log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
1510
1511 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
1512 TCU_THROW(NotSupportedError, "Importing image resource not supported");
1513
1514 if (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT)
1515 m_useDedicatedAllocation = true;
1516 }
1517 else
1518 {
1519 if (m_memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT && !IsWindows8OrGreater())
1520 TCU_THROW(NotSupportedError, "Memory handle type not supported by this OS");
1521
1522 const vk::VkPhysicalDeviceExternalBufferInfo info =
1523 {
1524 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
1525 DE_NULL,
1526
1527 0u,
1528 m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
1529 m_memoryHandleType
1530 };
1531 vk::VkExternalBufferProperties properties =
1532 {
1533 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
1534 DE_NULL,
1535 { 0u, 0u, 0u}
1536 };
1537 m_vki.getPhysicalDeviceExternalBufferProperties(m_physicalDevice, &info, &properties);
1538
1539 log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
1540
1541 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
1542 TCU_THROW(NotSupportedError, "Importing memory type not supported");
1543
1544 if (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT)
1545 m_useDedicatedAllocation = true;
1546 }
1547 #else
1548 DE_UNREF(m_useDedicatedAllocation);
1549 TCU_THROW(NotSupportedError, "OS not supported");
1550 #endif
1551 }
1552
iterate(void)1553 tcu::TestStatus Win32KeyedMutexTestInstance::iterate (void)
1554 {
1555 TestLog& log (m_context.getTestContext().getLog());
1556
1557 try
1558 {
1559 const deUint32 queueFamily = (deUint32)m_queueNdx;
1560
1561 const tcu::ScopedLogSection queuePairSection (log, "Queue-" + de::toString(queueFamily), "Queue-" + de::toString(queueFamily));
1562
1563 const vk::VkQueue queue (getDeviceQueue(m_vkd, *m_device, queueFamily, 0u));
1564 const vk::Unique<vk::VkCommandPool> commandPool (createCommandPool(m_vkd, *m_device, 0u, queueFamily));
1565 const vk::Unique<vk::VkCommandBuffer> commandBufferWrite (allocateCommandBuffer(m_vkd, *m_device, *commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1566 const vk::Unique<vk::VkCommandBuffer> commandBufferRead (allocateCommandBuffer(m_vkd, *m_device, *commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1567 vk::SimpleAllocator allocator (m_vkd, *m_device, vk::getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice));
1568 const std::vector<std::string> deviceExtensions;
1569 OperationContext operationContext (m_context.getUsedApiVersion(), m_vki, m_vkd, m_physicalDevice, *m_device, allocator, deviceExtensions, m_context.getBinaryCollection(), m_pipelineCacheData);
1570
1571 if (!checkQueueFlags(m_queueFamilies[m_queueNdx].queueFlags, vk::VK_QUEUE_GRAPHICS_BIT))
1572 TCU_THROW(NotSupportedError, "Operation not supported by the source queue");
1573
1574 const de::UniquePtr<DX11Operation> dx11Op (m_supportDX11->build(m_config.resource, m_memoryHandleType));
1575
1576 NativeHandle nativeHandleWrite = dx11Op->getNativeHandle(DX11Operation::BUFFER_VK_WRITE);
1577 const de::UniquePtr<Resource> resourceWrite (importResource(m_vkd, *m_device, m_config.resource, m_queueFamilyIndices, *m_supportReadOp, *m_supportWriteOp, nativeHandleWrite, m_memoryHandleType));
1578
1579 NativeHandle nativeHandleRead = dx11Op->getNativeHandle(DX11Operation::BUFFER_VK_READ);
1580 const de::UniquePtr<Resource> resourceRead (importResource(m_vkd, *m_device, m_config.resource, m_queueFamilyIndices, *m_supportReadOp, *m_supportWriteOp, nativeHandleRead, m_memoryHandleType));
1581
1582 const de::UniquePtr<Operation> writeOp (m_supportWriteOp->build(operationContext, *resourceWrite));
1583 const de::UniquePtr<Operation> readOp (m_supportReadOp->build(operationContext, *resourceRead));
1584
1585 const SyncInfo writeSync = writeOp->getSyncInfo();
1586 const SyncInfo readSync = readOp->getSyncInfo();
1587
1588 beginCommandBuffer(m_vkd, *commandBufferWrite);
1589 writeOp->recordCommands(*commandBufferWrite);
1590 recordWriteBarrier(m_vkd, *commandBufferWrite, *resourceWrite, writeSync, queueFamily, readSync);
1591 endCommandBuffer(m_vkd, *commandBufferWrite);
1592
1593 beginCommandBuffer(m_vkd, *commandBufferRead);
1594 recordReadBarrier(m_vkd, *commandBufferRead, *resourceRead, writeSync, readSync, queueFamily);
1595 readOp->recordCommands(*commandBufferRead);
1596 endCommandBuffer(m_vkd, *commandBufferRead);
1597
1598 {
1599 vk::VkDeviceMemory memory = resourceWrite->getMemory();
1600 deUint64 keyInit = DX11Operation::KEYED_MUTEX_VK_WRITE;
1601 deUint32 timeout = 0xFFFFFFFF; // INFINITE
1602 deUint64 keyExternal = DX11Operation::KEYED_MUTEX_DX_COPY;
1603 vk::VkWin32KeyedMutexAcquireReleaseInfoKHR keyedMutexInfo =
1604 {
1605 vk::VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR,
1606 DE_NULL,
1607
1608 1,
1609 &memory,
1610 &keyInit,
1611 &timeout,
1612
1613 1,
1614 &memory,
1615 &keyExternal,
1616 };
1617
1618 const vk::VkCommandBuffer commandBuffer = *commandBufferWrite;
1619 const vk::VkSubmitInfo submitInfo =
1620 {
1621 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1622 &keyedMutexInfo,
1623
1624 0u,
1625 DE_NULL,
1626 DE_NULL,
1627
1628 1u,
1629 &commandBuffer,
1630 0u,
1631 DE_NULL
1632 };
1633
1634 VK_CHECK(m_vkd.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
1635 }
1636
1637 dx11Op->copyMemory();
1638
1639 {
1640 vk::VkDeviceMemory memory = resourceRead->getMemory();
1641 deUint64 keyInternal = DX11Operation::KEYED_MUTEX_VK_VERIFY;
1642 deUint32 timeout = 0xFFFFFFFF; // INFINITE
1643 deUint64 keyExternal = DX11Operation::KEYED_MUTEX_DONE;
1644 vk::VkWin32KeyedMutexAcquireReleaseInfoKHR keyedMutexInfo =
1645 {
1646 vk::VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR,
1647 DE_NULL,
1648
1649 1,
1650 &memory,
1651 &keyInternal,
1652 &timeout,
1653
1654 1,
1655 &memory,
1656 &keyExternal,
1657 };
1658
1659 const vk::VkCommandBuffer commandBuffer = *commandBufferRead;
1660 const vk::VkSubmitInfo submitInfo =
1661 {
1662 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1663 &keyedMutexInfo,
1664
1665 0u,
1666 DE_NULL,
1667 DE_NULL,
1668
1669 1u,
1670 &commandBuffer,
1671 0u,
1672 DE_NULL
1673 };
1674
1675 VK_CHECK(m_vkd.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
1676 }
1677
1678 VK_CHECK(m_vkd.queueWaitIdle(queue));
1679
1680 {
1681 const Data expected = writeOp->getData();
1682 const Data actual = readOp->getData();
1683
1684 DE_ASSERT(expected.size == actual.size);
1685
1686 if (0 != deMemCmp(expected.data, actual.data, expected.size))
1687 {
1688 const size_t maxBytesLogged = 256;
1689 std::ostringstream expectedData;
1690 std::ostringstream actualData;
1691 size_t byteNdx = 0;
1692
1693 // Find first byte difference
1694 for (; actual.data[byteNdx] == expected.data[byteNdx]; byteNdx++)
1695 {
1696 // Nothing
1697 }
1698
1699 log << TestLog::Message << "First different byte at offset: " << byteNdx << TestLog::EndMessage;
1700
1701 // Log 8 previous bytes before the first incorrect byte
1702 if (byteNdx > 8)
1703 {
1704 expectedData << "... ";
1705 actualData << "... ";
1706
1707 byteNdx -= 8;
1708 }
1709 else
1710 byteNdx = 0;
1711
1712 for (size_t i = 0; i < maxBytesLogged && byteNdx < expected.size; i++, byteNdx++)
1713 {
1714 expectedData << (i > 0 ? ", " : "") << (deUint32)expected.data[byteNdx];
1715 actualData << (i > 0 ? ", " : "") << (deUint32)actual.data[byteNdx];
1716 }
1717
1718 if (expected.size > byteNdx)
1719 {
1720 expectedData << "...";
1721 actualData << "...";
1722 }
1723
1724 log << TestLog::Message << "Expected data: (" << expectedData.str() << ")" << TestLog::EndMessage;
1725 log << TestLog::Message << "Actual data: (" << actualData.str() << ")" << TestLog::EndMessage;
1726
1727 m_resultCollector.fail("Memory contents don't match");
1728 }
1729 }
1730 }
1731 catch (const tcu::NotSupportedError& error)
1732 {
1733 log << TestLog::Message << "Not supported: " << error.getMessage() << TestLog::EndMessage;
1734 }
1735 catch (const tcu::TestError& error)
1736 {
1737 m_resultCollector.fail(std::string("Exception: ") + error.getMessage());
1738 }
1739
1740 // Move to next queue
1741 {
1742 m_queueNdx++;
1743
1744 if (m_queueNdx >= m_queueFamilies.size())
1745 {
1746 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1747 }
1748 else
1749 {
1750 return tcu::TestStatus::incomplete();
1751 }
1752 }
1753 }
1754
1755 struct Progs
1756 {
initvkt::synchronization::__anon2a7f8c320111::Progs1757 void init (vk::SourceCollections& dst, TestConfig config) const
1758 {
1759 const de::UniquePtr<OperationSupport> readOp (makeOperationSupport(config.readOp, config.resource));
1760 const de::UniquePtr<OperationSupport> writeOp (makeOperationSupport(config.writeOp, config.resource));
1761
1762 readOp->initPrograms(dst);
1763 writeOp->initPrograms(dst);
1764 }
1765 };
1766
1767 } // anonymous
1768
createWin32KeyedMutexTest(tcu::TestContext & testCtx)1769 tcu::TestCaseGroup* createWin32KeyedMutexTest (tcu::TestContext& testCtx)
1770 {
1771 const struct
1772 {
1773 vk::VkExternalMemoryHandleTypeFlagBits memoryHandleTypeBuffer;
1774 vk::VkExternalMemoryHandleTypeFlagBits memoryHandleTypeImage;
1775 const char* nameSuffix;
1776 } cases[] =
1777 {
1778 {
1779 (vk::VkExternalMemoryHandleTypeFlagBits)0u, // DX11 doesn't support buffers with an NT handle
1780 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
1781 "_nt"
1782 },
1783 {
1784 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
1785 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT,
1786 "_kmt"
1787 },
1788 };
1789 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "win32_keyed_mutex", ""));
1790
1791 for (size_t writeOpNdx = 0; writeOpNdx < DE_LENGTH_OF_ARRAY(s_writeOps); ++writeOpNdx)
1792 for (size_t readOpNdx = 0; readOpNdx < DE_LENGTH_OF_ARRAY(s_readOps); ++readOpNdx)
1793 {
1794 const OperationName writeOp = s_writeOps[writeOpNdx];
1795 const OperationName readOp = s_readOps[readOpNdx];
1796 const std::string opGroupName = getOperationName(writeOp) + "_" + getOperationName(readOp);
1797 bool empty = true;
1798
1799 de::MovePtr<tcu::TestCaseGroup> opGroup (new tcu::TestCaseGroup(testCtx, opGroupName.c_str(), ""));
1800
1801 for (size_t resourceNdx = 0; resourceNdx < DE_LENGTH_OF_ARRAY(s_resourcesWin32KeyedMutex); ++resourceNdx)
1802 {
1803 const ResourceDescription& resource = s_resourcesWin32KeyedMutex[resourceNdx];
1804
1805 for (size_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1806 {
1807 if (resource.type == RESOURCE_TYPE_BUFFER && !cases[caseNdx].memoryHandleTypeBuffer)
1808 continue;
1809
1810 if (resource.type == RESOURCE_TYPE_IMAGE && !cases[caseNdx].memoryHandleTypeImage)
1811 continue;
1812
1813 std::string name = getResourceName(resource) + cases[caseNdx].nameSuffix;
1814
1815 if (isResourceSupported(writeOp, resource) && isResourceSupported(readOp, resource))
1816 {
1817 const TestConfig config (resource, writeOp, readOp, cases[caseNdx].memoryHandleTypeBuffer, cases[caseNdx].memoryHandleTypeImage);
1818
1819 opGroup->addChild(new InstanceFactory1<Win32KeyedMutexTestInstance, TestConfig, Progs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, "", Progs(), config));
1820 empty = false;
1821 }
1822 }
1823 }
1824
1825 if (!empty)
1826 group->addChild(opGroup.release());
1827 }
1828
1829 return group.release();
1830 }
1831
1832 } // synchronization
1833 } // vkt
1834