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