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