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