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