1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Synchronization tests for resources shared with DX11 keyed mutex
22 *//*--------------------------------------------------------------------*/
24 #include "vktSynchronizationWin32KeyedMutexTests.hpp"
26 #include "vkDeviceUtil.hpp"
27 #include "vkPlatform.hpp"
29 #include "vktTestCaseUtil.hpp"
31 #include "vktSynchronizationUtil.hpp"
32 #include "vktSynchronizationOperation.hpp"
33 #include "vktSynchronizationOperationTestData.hpp"
34 #include "vktExternalMemoryUtil.hpp"
36 #include "tcuResultCollector.hpp"
37 #include "tcuTestLog.hpp"
39 #if (DE_OS == DE_OS_WIN32)
40 # define WIN32_LEAN_AND_MEAN
44 # include "VersionHelpers.h"
46 # include "d3dcompiler.h"
48 typedef HRESULT (WINAPI * LPD3DX11COMPILEFROMMEMORY)(LPCSTR,
51 CONST D3D10_SHADER_MACRO*,
57 void*, /* ID3DX11ThreadPump */
64 using namespace vkt::ExternalMemoryUtil;
68 namespace synchronization
73 static const ResourceDescription s_resourcesWin32KeyedMutex[] =
75 { RESOURCE_TYPE_BUFFER, tcu::IVec4( 0x4000, 0, 0, 0), vk::VK_IMAGE_TYPE_LAST, vk::VK_FORMAT_UNDEFINED, (vk::VkImageAspectFlags)0 }, // 16 KiB (min max UBO range)
76 { RESOURCE_TYPE_BUFFER, tcu::IVec4(0x40000, 0, 0, 0), vk::VK_IMAGE_TYPE_LAST, vk::VK_FORMAT_UNDEFINED, (vk::VkImageAspectFlags)0 }, // 256 KiB
78 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R8_UNORM, vk::VK_IMAGE_ASPECT_COLOR_BIT },
79 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R16_UINT, vk::VK_IMAGE_ASPECT_COLOR_BIT },
80 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_ASPECT_COLOR_BIT },
81 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R16G16B16A16_UINT, vk::VK_IMAGE_ASPECT_COLOR_BIT },
82 { RESOURCE_TYPE_IMAGE, tcu::IVec4(128, 128, 0, 0), vk::VK_IMAGE_TYPE_2D, vk::VK_FORMAT_R32G32B32A32_SFLOAT, vk::VK_IMAGE_ASPECT_COLOR_BIT },
87 TestConfig (const ResourceDescription& resource_,
88 OperationName writeOp_,
89 OperationName readOp_,
90 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleTypeBuffer_,
91 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleTypeImage_)
92 : resource (resource_)
95 , memoryHandleTypeBuffer (memoryHandleTypeBuffer_)
96 , memoryHandleTypeImage (memoryHandleTypeImage_)
100 const ResourceDescription resource;
101 const OperationName writeOp;
102 const OperationName readOp;
103 const vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleTypeBuffer;
104 const vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleTypeImage;
107 bool checkQueueFlags (vk::VkQueueFlags availableFlags, const vk::VkQueueFlags neededFlags)
109 if ((availableFlags & (vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT)) != 0)
110 availableFlags |= vk::VK_QUEUE_TRANSFER_BIT;
112 return (availableFlags & neededFlags) != 0;
115 class SimpleAllocation : public vk::Allocation
118 SimpleAllocation (const vk::DeviceInterface& vkd,
120 const vk::VkDeviceMemory memory);
121 ~SimpleAllocation (void);
124 const vk::DeviceInterface& m_vkd;
125 const vk::VkDevice m_device;
128 SimpleAllocation::SimpleAllocation (const vk::DeviceInterface& vkd,
130 const vk::VkDeviceMemory memory)
131 : Allocation (memory, 0, DE_NULL)
137 SimpleAllocation::~SimpleAllocation (void)
139 m_vkd.freeMemory(m_device, getMemory(), DE_NULL);
142 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface& vkp)
146 std::vector<std::string> extensions;
148 extensions.push_back("VK_KHR_get_physical_device_properties2");
150 extensions.push_back("VK_KHR_external_memory_capabilities");
152 return vk::createDefaultInstance(vkp, std::vector<std::string>(), extensions);
154 catch (const vk::Error& error)
156 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
157 TCU_THROW(NotSupportedError, "Required external memory extensions not supported by the instance");
163 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki,
164 vk::VkInstance instance,
165 const tcu::CommandLine& cmdLine)
167 return vk::chooseDevice(vki, instance, cmdLine);
170 vk::Move<vk::VkDevice> createDevice (const vk::InstanceInterface& vki,
171 vk::VkPhysicalDevice physicalDevice)
173 const float priority = 0.0f;
174 const std::vector<vk::VkQueueFamilyProperties> queueFamilyProperties = vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
175 std::vector<deUint32> queueFamilyIndices (queueFamilyProperties.size(), 0xFFFFFFFFu);
176 std::vector<const char*> extensions;
178 extensions.push_back("VK_KHR_external_memory");
179 extensions.push_back("VK_KHR_external_memory_win32");
180 extensions.push_back("VK_KHR_win32_keyed_mutex");
181 extensions.push_back("VK_KHR_dedicated_allocation");
182 extensions.push_back("VK_KHR_get_memory_requirements2");
186 std::vector<vk::VkDeviceQueueCreateInfo> queues;
188 for (size_t ndx = 0; ndx < queueFamilyProperties.size(); ndx++)
190 const vk::VkDeviceQueueCreateInfo createInfo =
192 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
201 queues.push_back(createInfo);
204 const vk::VkDeviceCreateInfo createInfo =
206 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
210 (deUint32)queues.size(),
216 (deUint32)extensions.size(),
217 extensions.empty() ? DE_NULL : &extensions[0],
221 return vk::createDevice(vki, physicalDevice, &createInfo);
223 catch (const vk::Error& error)
225 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
226 TCU_THROW(NotSupportedError, "Required extensions not supported");
232 deUint32 chooseMemoryType (deUint32 bits)
234 DE_ASSERT(bits != 0);
236 for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++)
238 if ((bits & (1u << memoryTypeIndex)) != 0)
239 return memoryTypeIndex;
242 DE_FATAL("No supported memory types");
246 vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface& vkd,
248 const vk::VkMemoryRequirements& requirements,
249 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
250 NativeHandle& handle,
251 bool requiresDedicated,
255 const vk::VkMemoryDedicatedAllocateInfoKHR dedicatedInfo =
257 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
262 const vk::VkImportMemoryWin32HandleInfoKHR importInfo =
264 vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
265 (requiresDedicated) ? &dedicatedInfo : DE_NULL,
267 handle.getWin32Handle(),
271 const vk::VkMemoryAllocateInfo info =
273 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
276 chooseMemoryType(requirements.memoryTypeBits)
279 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info));
286 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
289 NativeHandle& nativeHandle,
290 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
292 const vk::VkBufferMemoryRequirementsInfo2KHR requirementsInfo =
294 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,
298 vk::VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
300 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
305 vk::VkMemoryRequirements2KHR requirements =
307 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
308 &dedicatedRequirements,
311 vkd.getBufferMemoryRequirements2KHR(device, &requirementsInfo, &requirements);
313 vk::Move<vk::VkDeviceMemory> memory = importMemory(vkd, device, requirements.memoryRequirements, externalType, nativeHandle, !!dedicatedRequirements.requiresDedicatedAllocation, buffer, DE_NULL);
314 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
316 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
319 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
322 NativeHandle& nativeHandle,
323 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
325 const vk::VkImageMemoryRequirementsInfo2KHR requirementsInfo =
327 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
331 vk::VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
333 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
338 vk::VkMemoryRequirements2KHR requirements =
340 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
341 &dedicatedRequirements,
344 vkd.getImageMemoryRequirements2KHR(device, &requirementsInfo, &requirements);
346 vk::Move<vk::VkDeviceMemory> memory = importMemory(vkd, device, requirements.memoryRequirements, externalType, nativeHandle, !!dedicatedRequirements.requiresDedicatedAllocation, DE_NULL, image);
347 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
349 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
352 de::MovePtr<Resource> importResource (const vk::DeviceInterface& vkd,
354 const ResourceDescription& resourceDesc,
355 const std::vector<deUint32>& queueFamilyIndices,
356 const OperationSupport& readOp,
357 const OperationSupport& writeOp,
358 NativeHandle& nativeHandle,
359 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
361 if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
363 const vk::VkExtent3D extent =
365 (deUint32)resourceDesc.size.x(),
366 de::max(1u, (deUint32)resourceDesc.size.y()),
367 de::max(1u, (deUint32)resourceDesc.size.z())
369 const vk::VkImageSubresourceRange subresourceRange =
371 resourceDesc.imageAspect,
377 const vk::VkImageSubresourceLayers subresourceLayers =
379 resourceDesc.imageAspect,
384 const vk::VkExternalMemoryImageCreateInfoKHR externalInfo =
386 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
388 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
390 const vk::VkImageCreateInfo createInfo =
392 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
396 resourceDesc.imageType,
397 resourceDesc.imageFormat,
401 vk::VK_SAMPLE_COUNT_1_BIT,
402 vk::VK_IMAGE_TILING_OPTIMAL,
403 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
404 vk::VK_SHARING_MODE_EXCLUSIVE,
406 (deUint32)queueFamilyIndices.size(),
407 &queueFamilyIndices[0],
408 vk::VK_IMAGE_LAYOUT_UNDEFINED
411 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo);
412 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *image, nativeHandle, externalType);
414 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
418 const vk::VkDeviceSize offset = 0u;
419 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
420 const vk::VkBufferUsageFlags usage = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags();
421 const vk::VkExternalMemoryBufferCreateInfoKHR externalInfo =
423 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
425 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
427 const vk::VkBufferCreateInfo createInfo =
429 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
435 vk::VK_SHARING_MODE_EXCLUSIVE,
436 (deUint32)queueFamilyIndices.size(),
437 &queueFamilyIndices[0]
439 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo);
440 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *buffer, nativeHandle, externalType);
442 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
446 void recordWriteBarrier (const vk::DeviceInterface& vkd,
447 vk::VkCommandBuffer commandBuffer,
448 const Resource& resource,
449 const SyncInfo& writeSync,
450 deUint32 writeQueueFamilyIndex,
451 const SyncInfo& readSync)
453 const vk::VkPipelineStageFlags srcStageMask = writeSync.stageMask;
454 const vk::VkAccessFlags srcAccessMask = writeSync.accessMask;
456 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
457 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
459 const vk::VkDependencyFlags dependencyFlags = 0;
461 if (resource.getType() == RESOURCE_TYPE_IMAGE)
463 const vk::VkImageMemoryBarrier barrier =
465 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
471 writeSync.imageLayout,
472 readSync.imageLayout,
474 writeQueueFamilyIndex,
475 VK_QUEUE_FAMILY_EXTERNAL_KHR,
477 resource.getImage().handle,
478 resource.getImage().subresourceRange
481 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
485 const vk::VkBufferMemoryBarrier barrier =
487 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
493 writeQueueFamilyIndex,
494 VK_QUEUE_FAMILY_EXTERNAL_KHR,
496 resource.getBuffer().handle,
501 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
505 void recordReadBarrier (const vk::DeviceInterface& vkd,
506 vk::VkCommandBuffer commandBuffer,
507 const Resource& resource,
508 const SyncInfo& writeSync,
509 const SyncInfo& readSync,
510 deUint32 readQueueFamilyIndex)
512 const vk::VkPipelineStageFlags srcStageMask = readSync.stageMask;
513 const vk::VkAccessFlags srcAccessMask = readSync.accessMask;
515 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
516 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
518 const vk::VkDependencyFlags dependencyFlags = 0;
520 if (resource.getType() == RESOURCE_TYPE_IMAGE)
522 const vk::VkImageMemoryBarrier barrier =
524 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
530 writeSync.imageLayout,
531 readSync.imageLayout,
533 VK_QUEUE_FAMILY_EXTERNAL_KHR,
534 readQueueFamilyIndex,
536 resource.getImage().handle,
537 resource.getImage().subresourceRange
540 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
544 const vk::VkBufferMemoryBarrier barrier =
546 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
552 VK_QUEUE_FAMILY_EXTERNAL_KHR,
553 readQueueFamilyIndex,
555 resource.getBuffer().handle,
560 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
564 std::vector<deUint32> getFamilyIndices (const std::vector<vk::VkQueueFamilyProperties>& properties)
566 std::vector<deUint32> indices (properties.size(), 0);
568 for (deUint32 ndx = 0; ndx < properties.size(); ndx++)
586 KEYED_MUTEX_INIT = 0,
587 KEYED_MUTEX_VK_WRITE = 1,
588 KEYED_MUTEX_DX_COPY = 2,
589 KEYED_MUTEX_VK_VERIFY = 3,
590 KEYED_MUTEX_DONE = 4,
593 #if (DE_OS == DE_OS_WIN32)
594 DX11Operation (const ResourceDescription& resourceDesc,
595 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleType,
596 ID3D11Device* pDevice,
597 ID3D11DeviceContext* pContext,
598 LPD3DX11COMPILEFROMMEMORY fnD3DX11CompileFromMemory,
599 pD3DCompile fnD3DCompile)
600 : m_resourceDesc (resourceDesc)
602 , m_pDevice (pDevice)
603 , m_pContext (pContext)
604 , m_fnD3DX11CompileFromMemory (fnD3DX11CompileFromMemory)
605 , m_fnD3DCompile (fnD3DCompile)
607 , m_pRenderTargetView (0)
608 , m_pVertexShader (0)
610 , m_pVertexBuffer (0)
612 , m_pSamplerLinear (0)
617 if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR ||
618 memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR)
620 m_isMemNtHandle = true;
622 m_isMemNtHandle = false;
624 m_securityAttributes.lpSecurityDescriptor = 0;
626 for (UINT i = 0; i < BUFFER_COUNT; i++)
628 m_pTexture[i] = NULL;
630 m_keyedMutex[i] = NULL;
633 if (m_resourceDesc.type == RESOURCE_TYPE_BUFFER)
635 // SHARED_NTHANDLE is not supported with CreateBuffer().
636 TCU_CHECK_INTERNAL(!m_isMemNtHandle);
638 D3D11_BUFFER_DESC descBuf = { };
639 descBuf.ByteWidth = (UINT)m_resourceDesc.size.x();
640 descBuf.Usage = D3D11_USAGE_DEFAULT;
641 descBuf.BindFlags = 0;
642 descBuf.CPUAccessFlags = 0;
643 descBuf.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
644 descBuf.StructureByteStride = 0;
646 for (UINT i = 0; i < BUFFER_COUNT; ++i)
648 hr = m_pDevice->CreateBuffer(&descBuf, NULL, &m_pBuffer[i]);
650 TCU_FAIL("Failed to create a buffer");
652 m_sharedMemHandle[i] = 0;
654 IDXGIResource* tempResource = NULL;
655 hr = m_pBuffer[i]->QueryInterface(__uuidof(IDXGIResource), (void**)&tempResource);
657 TCU_FAIL("Query interface of IDXGIResource failed");
658 hr = tempResource->GetSharedHandle(&m_sharedMemHandle[i]);
659 tempResource->Release();
661 TCU_FAIL("Failed to get DX shared handle");
663 hr = m_pBuffer[i]->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&m_keyedMutex[i]);
665 TCU_FAIL("Query interface of IDXGIKeyedMutex failed");
667 // Take ownership of the lock.
668 m_keyedMutex[i]->AcquireSync(KEYED_MUTEX_INIT, INFINITE);
671 // Release the buffer write lock for Vulkan to write into.
672 m_keyedMutex[BUFFER_VK_WRITE]->ReleaseSync(KEYED_MUTEX_VK_WRITE);
674 m_sharedMemSize = descBuf.ByteWidth;
675 m_sharedMemOffset = 0;
679 DE_ASSERT(m_resourceDesc.type == RESOURCE_TYPE_IMAGE);
681 for (UINT i = 0; i < BUFFER_COUNT; ++i)
683 D3D11_TEXTURE2D_DESC descColor = { };
684 descColor.Width = m_resourceDesc.size.x();
685 descColor.Height = m_resourceDesc.size.y();
686 descColor.MipLevels = 1;
687 descColor.ArraySize = 1;
688 descColor.Format = getDxgiFormat(m_resourceDesc.imageFormat);
689 descColor.SampleDesc.Count = 1;
690 descColor.SampleDesc.Quality = 0;
691 descColor.Usage = D3D11_USAGE_DEFAULT;
692 descColor.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
693 descColor.CPUAccessFlags = 0;
696 descColor.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
698 descColor.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
700 hr = m_pDevice->CreateTexture2D(&descColor, NULL, &m_pTexture[i]);
702 TCU_FAIL("Unable to create DX11 texture");
704 m_sharedMemHandle[i] = 0;
708 IDXGIResource1* tempResource1 = NULL;
709 hr = m_pTexture[i]->QueryInterface(__uuidof(IDXGIResource1), (void**)&tempResource1);
711 TCU_FAIL("Unable to query IDXGIResource1 interface");
713 hr = tempResource1->CreateSharedHandle(getSecurityAttributes(), DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, /*lpName*/NULL, &m_sharedMemHandle[i]);
714 tempResource1->Release();
716 TCU_FAIL("Enable to get DX shared handle");
720 IDXGIResource* tempResource = NULL;
721 hr = m_pTexture[i]->QueryInterface(__uuidof(IDXGIResource), (void**)&tempResource);
723 TCU_FAIL("Query interface of IDXGIResource failed");
724 hr = tempResource->GetSharedHandle(&m_sharedMemHandle[i]);
725 tempResource->Release();
727 TCU_FAIL("Failed to get DX shared handle");
730 hr = m_pTexture[i]->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&m_keyedMutex[i]);
732 TCU_FAIL("Unable to query DX11 keyed mutex interface");
734 // Take ownership of the lock.
735 m_keyedMutex[i]->AcquireSync(KEYED_MUTEX_INIT, INFINITE);
739 m_sharedMemOffset = 0;
741 hr = m_pDevice->CreateRenderTargetView(m_pTexture[BUFFER_VK_READ], NULL, &m_pRenderTargetView);
743 TCU_FAIL("Unable to create DX11 render target view");
745 m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);
747 // Setup the viewport
749 vp.Width = (FLOAT)m_resourceDesc.size.x();
750 vp.Height = (FLOAT)m_resourceDesc.size.y();
755 m_pContext->RSSetViewports(1, &vp);
757 // Compile the vertex shader
759 "Texture2D txDiffuse : register(t0);\n"
760 "SamplerState samLinear : register(s0);\n"
763 " float4 Pos : POSITION;\n"
764 " float2 Tex : TEXCOORD0;\n"
768 " float4 Pos : SV_POSITION;\n"
769 " float2 Tex : TEXCOORD0;\n"
771 "PS_INPUT VS(VS_INPUT input)\n"
773 " PS_INPUT output = (PS_INPUT)0;\n"
774 " output.Pos = input.Pos;\n"
775 " output.Tex = input.Tex;\n"
779 "float4 PS(PS_INPUT input) : SV_Target\n"
781 " return txDiffuse.Sample(samLinear, input.Tex);\n"
784 // Define the input layout
785 D3D11_INPUT_ELEMENT_DESC layout[] =
787 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
788 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
791 createShaders(shader, "VS", "vs_4_0", ARRAYSIZE(layout), layout, &m_pVertexShader, "PS", "ps_4_0", &m_pPixelShader);
799 SimpleVertex vertices[] =
801 { { -1.f, -1.f, 0.0f }, { 0.0f, 1.0f } },
802 { { -1.f, 1.f, 0.0f }, { 0.0f, 0.0f } },
803 { { 1.f, -1.f, 0.0f }, { 1.0f, 1.0f } },
804 { { 1.f, 1.f, 0.0f }, { 1.0f, 0.0f } },
807 D3D11_BUFFER_DESC bd = { };
808 bd.Usage = D3D11_USAGE_DEFAULT;
809 bd.ByteWidth = sizeof (vertices);
810 bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
811 bd.CPUAccessFlags = 0;
812 D3D11_SUBRESOURCE_DATA InitData = { };
813 InitData.pSysMem = vertices;
814 hr = m_pDevice->CreateBuffer(&bd, &InitData, &m_pVertexBuffer);
816 TCU_FAIL("Failed to create DX11 vertex buffer");
819 UINT stride = sizeof (SimpleVertex);
821 m_pContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);
823 // Set primitive topology
824 m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
828 D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = { };
829 SRVDesc.Format = getDxgiFormat(m_resourceDesc.imageFormat);
830 SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
831 SRVDesc.Texture2D.MipLevels = 1;
833 hr = m_pDevice->CreateShaderResourceView(m_pTexture[BUFFER_VK_WRITE], &SRVDesc, &m_pTextureRV);
835 TCU_FAIL("Failed to create DX11 resource view");
837 // Create the sample state
838 D3D11_SAMPLER_DESC sampDesc = { };
839 sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
840 sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
841 sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
842 sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
843 sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
845 sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
846 hr = m_pDevice->CreateSamplerState(&sampDesc, &m_pSamplerLinear);
848 TCU_FAIL("Failed to create DX11 sampler state");
850 // Release the lock for VK to write into the texture.
851 m_keyedMutex[BUFFER_VK_WRITE]->ReleaseSync(KEYED_MUTEX_VK_WRITE);
859 #endif // #if (DE_OS == DE_OS_WIN32)
861 NativeHandle getNativeHandle (Buffer buffer)
863 #if (DE_OS == DE_OS_WIN32)
864 return NativeHandle((m_isMemNtHandle) ? NativeHandle::WIN32HANDLETYPE_NT : NativeHandle::WIN32HANDLETYPE_KMT, vk::pt::Win32Handle(m_sharedMemHandle[buffer]));
867 return NativeHandle();
873 #if (DE_OS == DE_OS_WIN32)
874 m_keyedMutex[BUFFER_VK_WRITE]->AcquireSync(KEYED_MUTEX_DX_COPY, INFINITE);
876 if (m_resourceDesc.type == RESOURCE_TYPE_BUFFER) {
877 m_pContext->CopySubresourceRegion(m_pBuffer[BUFFER_VK_READ], 0, 0, 0, 0, m_pBuffer[BUFFER_VK_WRITE], 0, NULL);
879 m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);
881 const FLOAT gray[] = { 0.f, 0.f, 1.f, 1.f };
882 m_pContext->ClearRenderTargetView(m_pRenderTargetView, gray);
884 m_pContext->VSSetShader(m_pVertexShader, NULL, 0);
885 m_pContext->PSSetShader(m_pPixelShader, NULL, 0);
886 m_pContext->PSSetShaderResources(0, 1, &m_pTextureRV);
887 m_pContext->PSSetSamplers(0, 1, &m_pSamplerLinear);
888 m_pContext->Draw(4, 0);
891 m_keyedMutex[BUFFER_VK_WRITE]->ReleaseSync(KEYED_MUTEX_DONE);
892 m_keyedMutex[BUFFER_VK_READ]->ReleaseSync(KEYED_MUTEX_VK_VERIFY);
893 #endif // #if (DE_OS == DE_OS_WIN32)
896 #if (DE_OS == DE_OS_WIN32)
897 void d3dx11CompileShader (const char* shaderCode, const char * entryPoint, const char* shaderModel, ID3D10Blob** ppBlobOut)
901 ID3D10Blob* pErrorBlob;
902 hr = m_fnD3DX11CompileFromMemory (shaderCode,
916 pErrorBlob->Release();
919 TCU_FAIL("D3DX11CompileFromMemory failed to compile shader");
922 void d3dCompileShader (const char* shaderCode, const char * entryPoint, const char* shaderModel, ID3DBlob** ppBlobOut)
926 ID3DBlob* pErrorBlob;
927 hr = m_fnD3DCompile (shaderCode,
939 pErrorBlob->Release();
942 TCU_FAIL("D3DCompile failed to compile shader");
945 void createShaders (const char* shaderSrc,
946 const char* vsEntryPoint,
947 const char* vsShaderModel,
949 D3D11_INPUT_ELEMENT_DESC* pLayoutDesc,
950 ID3D11VertexShader** pVertexShader,
951 const char* psEntryPoint,
952 const char* psShaderModel,
953 ID3D11PixelShader** pPixelShader)
957 if (m_fnD3DX11CompileFromMemory) {
960 d3dx11CompileShader(shaderSrc, vsEntryPoint, vsShaderModel, &pVSBlob);
962 hr = m_pDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, pVertexShader);
964 TCU_FAIL("Failed to create DX11 vertex shader");
966 ID3D11InputLayout *pVertexLayout;
967 hr = m_pDevice->CreateInputLayout(pLayoutDesc, numLayoutDesc, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &pVertexLayout);
969 TCU_FAIL("Failed to create vertex input layout");
971 m_pContext->IASetInputLayout(pVertexLayout);
972 pVertexLayout->Release();
977 d3dx11CompileShader(shaderSrc, psEntryPoint, psShaderModel, &pPSBlob);
979 hr = m_pDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, pPixelShader);
981 TCU_FAIL("Failed to create DX11 pixel shader");
985 d3dCompileShader(shaderSrc, vsEntryPoint, vsShaderModel, &pVSBlob);
987 hr = m_pDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, pVertexShader);
989 TCU_FAIL("Failed to create DX11 vertex shader");
991 ID3D11InputLayout *pVertexLayout;
992 hr = m_pDevice->CreateInputLayout(pLayoutDesc, numLayoutDesc, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &pVertexLayout);
994 TCU_FAIL("Failed to create vertex input layout");
996 m_pContext->IASetInputLayout(pVertexLayout);
997 pVertexLayout->Release();
1002 d3dCompileShader(shaderSrc, psEntryPoint, psShaderModel, &pPSBlob);
1004 hr = m_pDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, pPixelShader);
1006 TCU_FAIL("Failed to create DX11 pixel shader");
1009 #endif // #if (DE_OS == DE_OS_WIN32)
1012 #if (DE_OS == DE_OS_WIN32)
1015 if (m_securityAttributes.lpSecurityDescriptor)
1017 freeSecurityDescriptor(m_securityAttributes.lpSecurityDescriptor);
1018 m_securityAttributes.lpSecurityDescriptor = NULL;
1022 m_pContext->ClearState();
1024 if (m_pRenderTargetView)
1026 m_pRenderTargetView->Release();
1027 m_pRenderTargetView = NULL;
1030 if (m_pSamplerLinear)
1032 m_pSamplerLinear->Release();
1033 m_pSamplerLinear = NULL;
1038 m_pTextureRV->Release();
1039 m_pTextureRV = NULL;
1042 if (m_pVertexBuffer)
1044 m_pVertexBuffer->Release();
1045 m_pVertexBuffer = NULL;
1048 if (m_pVertexShader)
1050 m_pVertexShader->Release();
1051 m_pVertexShader = NULL;
1056 m_pPixelShader->Release();
1057 m_pPixelShader = NULL;
1060 for (int i = 0; i < BUFFER_COUNT; i++)
1062 if (m_keyedMutex[i])
1064 m_keyedMutex[i]->AcquireSync(KEYED_MUTEX_DONE, INFINITE);
1065 m_keyedMutex[i]->Release();
1066 m_keyedMutex[i] = NULL;
1069 if (m_isMemNtHandle && m_sharedMemHandle[i]) {
1070 CloseHandle(m_sharedMemHandle[i]);
1071 m_sharedMemHandle[i] = 0;
1075 m_pBuffer[i]->Release();
1076 m_pBuffer[i] = NULL;
1079 if (m_pTexture[i]) {
1080 m_pTexture[i]->Release();
1081 m_pTexture[i] = NULL;
1086 static void* getSecurityDescriptor ()
1088 PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)deCalloc(SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof (void**));
1092 PSID* ppEveryoneSID = (PSID*)((PBYTE)pSD + SECURITY_DESCRIPTOR_MIN_LENGTH);
1093 PACL* ppACL = (PACL*)((PBYTE)ppEveryoneSID + sizeof(PSID*));
1095 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
1097 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
1098 AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, ppEveryoneSID);
1100 EXPLICIT_ACCESS ea = { };
1101 ea.grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
1102 ea.grfAccessMode = SET_ACCESS;
1103 ea.grfInheritance = INHERIT_ONLY;
1104 ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1105 ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1106 ea.Trustee.ptstrName = (LPTSTR)*ppEveryoneSID;
1108 SetEntriesInAcl(1, &ea, NULL, ppACL);
1110 SetSecurityDescriptorDacl(pSD, TRUE, *ppACL, FALSE);
1116 static void freeSecurityDescriptor (void* pSD)
1120 PSID* ppEveryoneSID = (PSID*)((PBYTE)pSD + SECURITY_DESCRIPTOR_MIN_LENGTH);
1121 PACL* ppACL = (PACL*)((PBYTE)ppEveryoneSID + sizeof(PSID*));
1124 FreeSid(*ppEveryoneSID);
1133 static DXGI_FORMAT getDxgiFormat (vk::VkFormat format)
1137 case vk::VK_FORMAT_R8_UNORM:
1138 return DXGI_FORMAT_R8_UNORM;
1139 case vk::VK_FORMAT_R16_UINT:
1140 return DXGI_FORMAT_R16_UINT;
1141 case vk::VK_FORMAT_R8G8B8A8_UNORM:
1142 return DXGI_FORMAT_R8G8B8A8_UNORM;
1143 case vk::VK_FORMAT_R16G16B16A16_UINT:
1144 return DXGI_FORMAT_R16G16B16A16_UINT;
1145 case vk::VK_FORMAT_R32G32B32A32_SFLOAT:
1146 return DXGI_FORMAT_R32G32B32A32_FLOAT;
1147 case vk::VK_FORMAT_D16_UNORM:
1148 return DXGI_FORMAT_D16_UNORM;
1149 case vk::VK_FORMAT_D32_SFLOAT:
1150 return DXGI_FORMAT_D32_FLOAT;
1152 TCU_CHECK_INTERNAL(!"Unsupported DXGI format");
1153 return DXGI_FORMAT_UNKNOWN;
1157 ResourceDescription m_resourceDesc;
1159 deUint64 m_sharedMemSize;
1160 deUint64 m_sharedMemOffset;
1161 HANDLE m_sharedMemHandle[BUFFER_COUNT];
1162 bool m_isMemNtHandle;
1164 ID3D11Device* m_pDevice;
1165 ID3D11DeviceContext* m_pContext;
1166 LPD3DX11COMPILEFROMMEMORY m_fnD3DX11CompileFromMemory;
1167 pD3DCompile m_fnD3DCompile;
1169 ID3D11RenderTargetView* m_pRenderTargetView;
1170 ID3D11VertexShader* m_pVertexShader;
1171 ID3D11PixelShader* m_pPixelShader;
1172 ID3D11Buffer* m_pVertexBuffer;
1173 ID3D11ShaderResourceView* m_pTextureRV;
1174 ID3D11SamplerState* m_pSamplerLinear;
1176 ID3D11Texture2D* m_pTexture[BUFFER_COUNT];
1177 ID3D11Buffer* m_pBuffer[BUFFER_COUNT];
1178 IDXGIKeyedMutex* m_keyedMutex[BUFFER_COUNT];
1180 SECURITY_ATTRIBUTES m_securityAttributes;
1182 SECURITY_ATTRIBUTES* getSecurityAttributes ()
1184 m_securityAttributes.nLength = sizeof (SECURITY_ATTRIBUTES);
1185 m_securityAttributes.bInheritHandle = TRUE;
1186 if (!m_securityAttributes.lpSecurityDescriptor)
1187 m_securityAttributes.lpSecurityDescriptor = getSecurityDescriptor();
1189 return &m_securityAttributes;
1191 #endif // #if (DE_OS == DE_OS_WIN32)
1194 class DX11OperationSupport
1197 DX11OperationSupport (const vk::InstanceInterface& vki,
1198 vk::VkPhysicalDevice physicalDevice,
1199 const ResourceDescription& resourceDesc)
1200 : m_resourceDesc (resourceDesc)
1201 #if (DE_OS == DE_OS_WIN32)
1204 , m_hD3DCompilerLib (0)
1206 , m_fnD3D11CreateDevice (0)
1207 , m_fnD3DX11CompileFromMemory (0)
1208 , m_fnD3DCompile (0)
1211 #if (DE_OS == DE_OS_WIN32)
1214 vk::VkPhysicalDeviceIDPropertiesKHR propertiesId = { vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR };
1215 vk::VkPhysicalDeviceProperties2KHR properties = { vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR };
1217 properties.pNext = &propertiesId;
1219 vki.getPhysicalDeviceProperties2KHR(physicalDevice, &properties);
1220 if (!propertiesId.deviceLUIDValid)
1221 TCU_FAIL("Physical device deviceLUIDValid is not valid");
1224 m_hD3D11Lib = LoadLibrary("d3d11.dll");
1226 TCU_FAIL("Failed to load d3d11.dll");
1229 m_fnD3D11CreateDevice = (LPD3D11CREATEDEVICE) GetProcAddress(m_hD3D11Lib, "D3D11CreateDevice");
1230 if (!m_fnD3D11CreateDevice)
1231 TCU_FAIL("Unable to find D3D11CreateDevice() function");
1233 m_hD3DX11Lib = LoadLibrary("d3dx11_42.dll");
1235 m_fnD3DX11CompileFromMemory = (LPD3DX11COMPILEFROMMEMORY) GetProcAddress(m_hD3DX11Lib, "D3DX11CompileFromMemory");
1238 m_hD3DCompilerLib = LoadLibrary("d3dcompiler_43.dll");
1239 if (!m_hD3DCompilerLib)
1240 m_hD3DCompilerLib = LoadLibrary("d3dcompiler_47.dll");
1241 if (!m_hD3DCompilerLib)
1242 TCU_FAIL("Unable to load DX11 d3dcompiler_43.dll or d3dcompiler_47.dll");
1244 m_fnD3DCompile = (pD3DCompile)GetProcAddress(m_hD3DCompilerLib, "D3DCompile");
1245 if (!m_fnD3DCompile)
1246 TCU_FAIL("Unable to load find D3DCompile");
1249 m_hDxgiLib = LoadLibrary("dxgi.dll");
1251 TCU_FAIL("Unable to load DX11 dxgi.dll");
1253 typedef HRESULT (WINAPI *LPCREATEDXGIFACTORY1)(REFIID riid, void** ppFactory);
1254 LPCREATEDXGIFACTORY1 CreateDXGIFactory1 = (LPCREATEDXGIFACTORY1)GetProcAddress(m_hDxgiLib, "CreateDXGIFactory1");
1255 if (!CreateDXGIFactory1)
1256 TCU_FAIL("Unable to load find CreateDXGIFactory1");
1258 IDXGIFactory1* pFactory = NULL;
1259 hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), (void**)&pFactory);
1261 TCU_FAIL("Unable to create IDXGIFactory interface");
1263 IDXGIAdapter *pAdapter = NULL;
1264 for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
1266 DXGI_ADAPTER_DESC desc;
1267 pAdapter->GetDesc(&desc);
1269 if (deMemCmp(&desc.AdapterLuid, propertiesId.deviceLUID, VK_LUID_SIZE_KHR) == 0)
1272 pFactory->Release();
1274 D3D_FEATURE_LEVEL fLevel[] = {D3D_FEATURE_LEVEL_11_0};
1275 UINT devflags = D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS | // no separate D3D11 worker thread
1277 D3D11_CREATE_DEVICE_DEBUG | // useful for diagnosing DX failures
1279 D3D11_CREATE_DEVICE_SINGLETHREADED;
1281 hr = m_fnD3D11CreateDevice (pAdapter,
1282 pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE,
1286 DE_LENGTH_OF_ARRAY(fLevel),
1293 pAdapter->Release();
1297 TCU_FAIL("Failed to created DX11 device");
1299 TCU_FAIL("Failed to created DX11 context");
1302 DE_UNREF(physicalDevice);
1303 TCU_THROW(NotSupportedError, "OS not supported");
1307 ~DX11OperationSupport ()
1309 #if (DE_OS == DE_OS_WIN32)
1314 #if (DE_OS == DE_OS_WIN32)
1318 m_pContext->Release();
1323 m_pDevice->Release();
1329 FreeLibrary(m_hDxgiLib);
1333 if (m_hD3DCompilerLib)
1335 FreeLibrary(m_hD3DCompilerLib);
1336 m_hD3DCompilerLib = 0;
1341 FreeLibrary(m_hD3DX11Lib);
1347 FreeLibrary(m_hD3D11Lib);
1354 virtual de::MovePtr<DX11Operation> build (const ResourceDescription& resourceDesc, vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleType) const
1356 #if (DE_OS == DE_OS_WIN32)
1357 return de::MovePtr<DX11Operation>(new DX11Operation(resourceDesc, memoryHandleType, m_pDevice, m_pContext, m_fnD3DX11CompileFromMemory, m_fnD3DCompile));
1359 DE_UNREF(resourceDesc);
1360 DE_UNREF(memoryHandleType);
1361 TCU_THROW(NotSupportedError, "OS not supported");
1366 const ResourceDescription m_resourceDesc;
1368 #if (DE_OS == DE_OS_WIN32)
1369 typedef HRESULT (WINAPI *LPD3D11CREATEDEVICE)(IDXGIAdapter*,
1373 const D3D_FEATURE_LEVEL*,
1378 ID3D11DeviceContext**);
1380 HMODULE m_hD3D11Lib;
1381 HMODULE m_hD3DX11Lib;
1382 HMODULE m_hD3DCompilerLib;
1384 LPD3D11CREATEDEVICE m_fnD3D11CreateDevice;
1385 LPD3DX11COMPILEFROMMEMORY m_fnD3DX11CompileFromMemory;
1386 pD3DCompile m_fnD3DCompile;
1387 ID3D11Device* m_pDevice;
1388 ID3D11DeviceContext* m_pContext;
1392 class Win32KeyedMutexTestInstance : public TestInstance
1395 Win32KeyedMutexTestInstance (Context& context,
1398 virtual tcu::TestStatus iterate (void);
1401 const TestConfig m_config;
1402 const de::UniquePtr<OperationSupport> m_supportWriteOp;
1403 const de::UniquePtr<OperationSupport> m_supportReadOp;
1405 const vk::Unique<vk::VkInstance> m_instance;
1407 const vk::InstanceDriver m_vki;
1408 const vk::VkPhysicalDevice m_physicalDevice;
1409 const std::vector<vk::VkQueueFamilyProperties> m_queueFamilies;
1410 const std::vector<deUint32> m_queueFamilyIndices;
1411 const vk::Unique<vk::VkDevice> m_device;
1412 const vk::DeviceDriver m_vkd;
1414 const de::UniquePtr<DX11OperationSupport> m_supportDX11;
1416 const vk::VkExternalMemoryHandleTypeFlagBitsKHR m_memoryHandleType;
1418 // \todo Should this be moved to the group same way as in the other tests?
1419 PipelineCacheData m_pipelineCacheData;
1420 tcu::ResultCollector m_resultCollector;
1423 bool m_useDedicatedAllocation;
1426 Win32KeyedMutexTestInstance::Win32KeyedMutexTestInstance (Context& context,
1428 : TestInstance (context)
1430 , m_supportWriteOp (makeOperationSupport(config.writeOp, config.resource))
1431 , m_supportReadOp (makeOperationSupport(config.readOp, config.resource))
1433 , m_instance (createInstance(context.getPlatformInterface()))
1435 , m_vki (context.getPlatformInterface(), *m_instance)
1436 , m_physicalDevice (getPhysicalDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
1437 , m_queueFamilies (vk::getPhysicalDeviceQueueFamilyProperties(m_vki, m_physicalDevice))
1438 , m_queueFamilyIndices (getFamilyIndices(m_queueFamilies))
1439 , m_device (createDevice(m_vki, m_physicalDevice))
1440 , m_vkd (m_vki, *m_device)
1442 , m_supportDX11 (new DX11OperationSupport(m_vki, m_physicalDevice, config.resource))
1444 , m_memoryHandleType ((m_config.resource.type == RESOURCE_TYPE_IMAGE) ? m_config.memoryHandleTypeImage : m_config.memoryHandleTypeBuffer)
1446 , m_resultCollector (context.getTestContext().getLog())
1449 , m_useDedicatedAllocation (false)
1451 #if (DE_OS == DE_OS_WIN32)
1452 TestLog& log = m_context.getTestContext().getLog();
1454 // Check resource support
1455 if (m_config.resource.type == RESOURCE_TYPE_IMAGE)
1457 if (m_memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR && !IsWindows8OrGreater())
1458 TCU_THROW(NotSupportedError, "Memory handle type not supported by this OS");
1460 const vk::VkPhysicalDeviceExternalImageFormatInfoKHR externalInfo =
1462 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
1466 const vk::VkPhysicalDeviceImageFormatInfo2KHR imageFormatInfo =
1468 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
1470 m_config.resource.imageFormat,
1471 m_config.resource.imageType,
1472 vk::VK_IMAGE_TILING_OPTIMAL,
1473 m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
1476 vk::VkExternalImageFormatPropertiesKHR externalProperties =
1478 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
1482 vk::VkImageFormatProperties2KHR formatProperties =
1484 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
1485 &externalProperties,
1494 VK_CHECK(m_vki.getPhysicalDeviceImageFormatProperties2KHR(m_physicalDevice, &imageFormatInfo, &formatProperties));
1496 // \todo How to log this nicely?
1497 log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
1499 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
1500 TCU_THROW(NotSupportedError, "Importing image resource not supported");
1502 if (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR)
1503 m_useDedicatedAllocation = true;
1507 if (m_memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR && !IsWindows8OrGreater())
1508 TCU_THROW(NotSupportedError, "Memory handle type not supported by this OS");
1510 const vk::VkPhysicalDeviceExternalBufferInfoKHR info =
1512 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
1516 m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
1519 vk::VkExternalBufferPropertiesKHR properties =
1521 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
1525 m_vki.getPhysicalDeviceExternalBufferPropertiesKHR(m_physicalDevice, &info, &properties);
1527 log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
1529 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
1530 TCU_THROW(NotSupportedError, "Importing memory type not supported");
1532 if (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR)
1533 m_useDedicatedAllocation = true;
1536 DE_UNREF(m_useDedicatedAllocation);
1537 TCU_THROW(NotSupportedError, "OS not supported");
1541 tcu::TestStatus Win32KeyedMutexTestInstance::iterate (void)
1543 TestLog& log (m_context.getTestContext().getLog());
1547 const deUint32 queueFamily = (deUint32)m_queueNdx;
1549 const tcu::ScopedLogSection queuePairSection (log, "Queue-" + de::toString(queueFamily), "Queue-" + de::toString(queueFamily));
1551 const vk::VkQueue queue (getDeviceQueue(m_vkd, *m_device, queueFamily, 0u));
1552 const vk::Unique<vk::VkCommandPool> commandPool (createCommandPool(m_vkd, *m_device, 0u, queueFamily));
1553 const vk::Unique<vk::VkCommandBuffer> commandBufferWrite (allocateCommandBuffer(m_vkd, *m_device, *commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1554 const vk::Unique<vk::VkCommandBuffer> commandBufferRead (allocateCommandBuffer(m_vkd, *m_device, *commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1555 vk::SimpleAllocator allocator (m_vkd, *m_device, vk::getPhysicalDeviceMemoryProperties(m_vki, m_physicalDevice));
1556 const std::vector<std::string> deviceExtensions;
1557 OperationContext operationContext (m_vki, m_vkd, m_physicalDevice, *m_device, allocator, deviceExtensions, m_context.getBinaryCollection(), m_pipelineCacheData);
1559 if (!checkQueueFlags(m_queueFamilies[m_queueNdx].queueFlags, vk::VK_QUEUE_GRAPHICS_BIT))
1560 TCU_THROW(NotSupportedError, "Operation not supported by the source queue");
1562 const de::UniquePtr<DX11Operation> dx11Op (m_supportDX11->build(m_config.resource, m_memoryHandleType));
1564 NativeHandle nativeHandleWrite = dx11Op->getNativeHandle(DX11Operation::BUFFER_VK_WRITE);
1565 const de::UniquePtr<Resource> resourceWrite (importResource(m_vkd, *m_device, m_config.resource, m_queueFamilyIndices, *m_supportReadOp, *m_supportWriteOp, nativeHandleWrite, m_memoryHandleType));
1567 NativeHandle nativeHandleRead = dx11Op->getNativeHandle(DX11Operation::BUFFER_VK_READ);
1568 const de::UniquePtr<Resource> resourceRead (importResource(m_vkd, *m_device, m_config.resource, m_queueFamilyIndices, *m_supportReadOp, *m_supportWriteOp, nativeHandleRead, m_memoryHandleType));
1570 const de::UniquePtr<Operation> writeOp (m_supportWriteOp->build(operationContext, *resourceWrite));
1571 const de::UniquePtr<Operation> readOp (m_supportReadOp->build(operationContext, *resourceRead));
1573 const SyncInfo writeSync = writeOp->getSyncInfo();
1574 const SyncInfo readSync = readOp->getSyncInfo();
1576 beginCommandBuffer(m_vkd, *commandBufferWrite);
1577 writeOp->recordCommands(*commandBufferWrite);
1578 recordWriteBarrier(m_vkd, *commandBufferWrite, *resourceWrite, writeSync, queueFamily, readSync);
1579 endCommandBuffer(m_vkd, *commandBufferWrite);
1581 beginCommandBuffer(m_vkd, *commandBufferRead);
1582 recordReadBarrier(m_vkd, *commandBufferRead, *resourceRead, writeSync, readSync, queueFamily);
1583 readOp->recordCommands(*commandBufferRead);
1584 endCommandBuffer(m_vkd, *commandBufferRead);
1587 vk::VkDeviceMemory memory = resourceWrite->getMemory();
1588 deUint64 keyInit = DX11Operation::KEYED_MUTEX_VK_WRITE;
1589 deUint32 timeout = 0xFFFFFFFF; // INFINITE
1590 deUint64 keyExternal = DX11Operation::KEYED_MUTEX_DX_COPY;
1591 vk::VkWin32KeyedMutexAcquireReleaseInfoKHR keyedMutexInfo =
1593 vk::VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR,
1606 const vk::VkCommandBuffer commandBuffer = *commandBufferWrite;
1607 const vk::VkSubmitInfo submitInfo =
1609 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1622 VK_CHECK(m_vkd.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
1625 dx11Op->copyMemory();
1628 vk::VkDeviceMemory memory = resourceRead->getMemory();
1629 deUint64 keyInternal = DX11Operation::KEYED_MUTEX_VK_VERIFY;
1630 deUint32 timeout = 0xFFFFFFFF; // INFINITE
1631 deUint64 keyExternal = DX11Operation::KEYED_MUTEX_DONE;
1632 vk::VkWin32KeyedMutexAcquireReleaseInfoKHR keyedMutexInfo =
1634 vk::VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR,
1647 const vk::VkCommandBuffer commandBuffer = *commandBufferRead;
1648 const vk::VkSubmitInfo submitInfo =
1650 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1663 VK_CHECK(m_vkd.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
1666 VK_CHECK(m_vkd.queueWaitIdle(queue));
1669 const Data expected = writeOp->getData();
1670 const Data actual = readOp->getData();
1672 DE_ASSERT(expected.size == actual.size);
1674 if (0 != deMemCmp(expected.data, actual.data, expected.size))
1676 const size_t maxBytesLogged = 256;
1677 std::ostringstream expectedData;
1678 std::ostringstream actualData;
1681 // Find first byte difference
1682 for (; actual.data[byteNdx] == expected.data[byteNdx]; byteNdx++)
1687 log << TestLog::Message << "First different byte at offset: " << byteNdx << TestLog::EndMessage;
1689 // Log 8 previous bytes before the first incorrect byte
1692 expectedData << "... ";
1693 actualData << "... ";
1700 for (size_t i = 0; i < maxBytesLogged && byteNdx < expected.size; i++, byteNdx++)
1702 expectedData << (i > 0 ? ", " : "") << (deUint32)expected.data[byteNdx];
1703 actualData << (i > 0 ? ", " : "") << (deUint32)actual.data[byteNdx];
1706 if (expected.size > byteNdx)
1708 expectedData << "...";
1709 actualData << "...";
1712 log << TestLog::Message << "Expected data: (" << expectedData.str() << ")" << TestLog::EndMessage;
1713 log << TestLog::Message << "Actual data: (" << actualData.str() << ")" << TestLog::EndMessage;
1715 m_resultCollector.fail("Memory contents don't match");
1719 catch (const tcu::NotSupportedError& error)
1721 log << TestLog::Message << "Not supported: " << error.getMessage() << TestLog::EndMessage;
1723 catch (const tcu::TestError& error)
1725 m_resultCollector.fail(std::string("Exception: ") + error.getMessage());
1728 // Move to next queue
1732 if (m_queueNdx >= m_queueFamilies.size())
1734 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1738 return tcu::TestStatus::incomplete();
1745 void init (vk::SourceCollections& dst, TestConfig config) const
1747 const de::UniquePtr<OperationSupport> readOp (makeOperationSupport(config.readOp, config.resource));
1748 const de::UniquePtr<OperationSupport> writeOp (makeOperationSupport(config.writeOp, config.resource));
1750 readOp->initPrograms(dst);
1751 writeOp->initPrograms(dst);
1757 tcu::TestCaseGroup* createWin32KeyedMutexTest (tcu::TestContext& testCtx)
1761 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleTypeBuffer;
1762 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleTypeImage;
1763 const char* nameSuffix;
1767 (vk::VkExternalMemoryHandleTypeFlagBitsKHR)0u, // DX11 doesn't support buffers with an NT handle
1768 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR,
1772 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1773 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR,
1777 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "win32_keyed_mutex", ""));
1779 for (size_t writeOpNdx = 0; writeOpNdx < DE_LENGTH_OF_ARRAY(s_writeOps); ++writeOpNdx)
1780 for (size_t readOpNdx = 0; readOpNdx < DE_LENGTH_OF_ARRAY(s_readOps); ++readOpNdx)
1782 const OperationName writeOp = s_writeOps[writeOpNdx];
1783 const OperationName readOp = s_readOps[readOpNdx];
1784 const std::string opGroupName = getOperationName(writeOp) + "_" + getOperationName(readOp);
1787 de::MovePtr<tcu::TestCaseGroup> opGroup (new tcu::TestCaseGroup(testCtx, opGroupName.c_str(), ""));
1789 for (size_t resourceNdx = 0; resourceNdx < DE_LENGTH_OF_ARRAY(s_resourcesWin32KeyedMutex); ++resourceNdx)
1791 const ResourceDescription& resource = s_resourcesWin32KeyedMutex[resourceNdx];
1793 for (size_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1795 if (resource.type == RESOURCE_TYPE_BUFFER && !cases[caseNdx].memoryHandleTypeBuffer)
1798 if (resource.type == RESOURCE_TYPE_IMAGE && !cases[caseNdx].memoryHandleTypeImage)
1801 std::string name = getResourceName(resource) + cases[caseNdx].nameSuffix;
1803 if (isResourceSupported(writeOp, resource) && isResourceSupported(readOp, resource))
1805 const TestConfig config (resource, writeOp, readOp, cases[caseNdx].memoryHandleTypeBuffer, cases[caseNdx].memoryHandleTypeImage);
1807 opGroup->addChild(new InstanceFactory1<Win32KeyedMutexTestInstance, TestConfig, Progs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, "", Progs(), config));
1814 group->addChild(opGroup.release());
1817 return group.release();
1820 } // synchronization