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