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