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