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