121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang/*-------------------------------------------------------------------------
221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * Vulkan Conformance Tests
321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * ------------------------
421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * Copyright (c) 2015 Google Inc.
621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
7978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * Licensed under the Apache License, Version 2.0 (the "License");
8978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * you may not use this file except in compliance with the License.
9978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * You may obtain a copy of the License at
1021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
11978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos *      http://www.apache.org/licenses/LICENSE-2.0
1221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
13978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * Unless required by applicable law or agreed to in writing, software
14978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * distributed under the License is distributed on an "AS IS" BASIS,
15978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * See the License for the specific language governing permissions and
17978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * limitations under the License.
1821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
1921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*!
2021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * \file
2121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * \brief Test Case Skeleton Based on Compute Shaders
2221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*--------------------------------------------------------------------*/
2321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
2421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang#include "vktSpvAsmComputeShaderCase.hpp"
2521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
2621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang#include "deSharedPtr.hpp"
2705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang#include "deSTLUtil.hpp"
2821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
2921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang#include "vkBuilderUtil.hpp"
3021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang#include "vkMemUtil.hpp"
318977777244ce058cb79e1cf3b43e528322e8308cLei Zhang#include "vkPlatform.hpp"
3221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang#include "vkRefUtil.hpp"
3321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang#include "vkQueryUtil.hpp"
3468e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos#include "vkTypeUtil.hpp"
3521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
3621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhangnamespace
3721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
3821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
3921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhangusing namespace vk;
4021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhangusing std::vector;
4121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
42cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyntypedef vkt::SpirVAssembly::AllocationMp			AllocationMp;
43cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyntypedef vkt::SpirVAssembly::AllocationSp			AllocationSp;
44cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyn
45cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyntypedef Unique<VkBuffer>							BufferHandleUp;
46cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyntypedef de::SharedPtr<BufferHandleUp>				BufferHandleSp;
4721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
4821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang/*--------------------------------------------------------------------*//*!
4921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * \brief Create storage buffer, allocate and bind memory for the buffer
5021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
5121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * The memory is created as host visible and passed back as a vk::Allocation
5221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * instance via outMemory.
5321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*--------------------------------------------------------------------*/
5405e91483c6f2f48b408ed1a638cbb32468ed8dfaLei ZhangMove<VkBuffer> createBufferAndBindMemory (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorType dtype, Allocator& allocator, size_t numBytes, AllocationMp* outMemory)
5521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
56318e6d042b1aaa15327342b39967f0ae97d23347Pyry Haulos	VkBufferUsageFlags			usageBit		= (VkBufferUsageFlags)0;
5705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
5805e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	switch (dtype)
5905e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	{
6005e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:	usageBit = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; break;
6105e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:	usageBit = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break;
6205e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		default:								DE_ASSERT(false);
6305e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	}
6405e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
6505e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	const VkBufferCreateInfo bufferCreateInfo	=
6621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	{
6721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// sType
6821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		DE_NULL,								// pNext
6968e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		0u,										// flags
7021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		numBytes,								// size
7105e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		usageBit,								// usage
7221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		VK_SHARING_MODE_EXCLUSIVE,				// sharingMode
7321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		0u,										// queueFamilyCount
7421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		DE_NULL,								// pQueueFamilyIndices
7521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	};
7621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
7721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	Move<VkBuffer>				buffer			(createBuffer(vkdi, device, &bufferCreateInfo));
7821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	const VkMemoryRequirements	requirements	= getBufferMemoryRequirements(vkdi, device, *buffer);
7921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	AllocationMp				bufferMemory	= allocator.allocate(requirements, MemoryRequirement::HostVisible);
8021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
8121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	VK_CHECK(vkdi.bindBufferMemory(device, *buffer, bufferMemory->getMemory(), bufferMemory->getOffset()));
8221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	*outMemory = bufferMemory;
8321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
8421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	return buffer;
8521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
8621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
8721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhangvoid setMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, const void* data)
8821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
8921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	void* const hostPtr = destAlloc->getHostPtr();
9021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
9121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	deMemcpy((deUint8*)hostPtr, data, numBytes);
9221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes);
9321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
9421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
950e95062c203b163b84428f1e3781c0243c51bc29Lei Zhangvoid fillMemoryWithValue (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, deUint8 value)
9621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
9721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	void* const hostPtr = destAlloc->getHostPtr();
9821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
990e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang	deMemset((deUint8*)hostPtr, value, numBytes);
10021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes);
10121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
10221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
10391459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughesvoid invalidateMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* srcAlloc, size_t numBytes)
10491459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes{
10591459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes	invalidateMappedMemoryRange(vkdi, device, srcAlloc->getMemory(), srcAlloc->getOffset(), numBytes);
10691459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes}
10791459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes
10821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang/*--------------------------------------------------------------------*//*!
10905e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang * \brief Create a descriptor set layout with the given descriptor types
11021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
11105e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang * All descriptors are created for compute pipeline.
11221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*--------------------------------------------------------------------*/
11305e91483c6f2f48b408ed1a638cbb32468ed8dfaLei ZhangMove<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkdi, const VkDevice& device, const vector<VkDescriptorType>& dtypes)
11421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
11521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	DescriptorSetLayoutBuilder builder;
11621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
11705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	for (size_t bindingNdx = 0; bindingNdx < dtypes.size(); ++bindingNdx)
11805e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		builder.addSingleBinding(dtypes[bindingNdx], VK_SHADER_STAGE_COMPUTE_BIT);
11921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
12021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	return builder.build(vkdi, device);
12121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
12221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
12321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang/*--------------------------------------------------------------------*//*!
12421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * \brief Create a pipeline layout with one descriptor set
12521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*--------------------------------------------------------------------*/
12605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei ZhangMove<VkPipelineLayout> createPipelineLayout (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorSetLayout descriptorSetLayout, const vkt::SpirVAssembly::BufferSp& pushConstants)
12721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
12805e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	VkPipelineLayoutCreateInfo		createInfo	=
12921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	{
13021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// sType
13121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		DE_NULL,										// pNext
13268e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		(VkPipelineLayoutCreateFlags)0,
13321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		1u,												// descriptorSetCount
13421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		&descriptorSetLayout,							// pSetLayouts
13521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		0u,												// pushConstantRangeCount
13621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		DE_NULL,										// pPushConstantRanges
13721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	};
13821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
13905e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	VkPushConstantRange				range		=
14005e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	{
14105e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		VK_SHADER_STAGE_COMPUTE_BIT,					// stageFlags
14205e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		0,												// offset
14305e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		0,												// size
14405e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	};
14505e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
14605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	if (pushConstants != DE_NULL)
14705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	{
1480fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		vector<deUint8> pushConstantsBytes;
1490fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		pushConstants->getBytes(pushConstantsBytes);
1500fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi
1510fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		range.size							= static_cast<deUint32>(pushConstantsBytes.size());
15205e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		createInfo.pushConstantRangeCount	= 1;
15305e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		createInfo.pPushConstantRanges		= &range;
15405e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	}
15505e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
15605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	return createPipelineLayout(vkdi, device, &createInfo);
15721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
15821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
15921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang/*--------------------------------------------------------------------*//*!
16005e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang * \brief Create a one-time descriptor pool for one descriptor set that
16105e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang * support the given descriptor types.
16221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*--------------------------------------------------------------------*/
16305e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhanginline Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkdi, const VkDevice& device, const vector<VkDescriptorType>& dtypes)
16421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
16505e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	DescriptorPoolBuilder builder;
16605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
16705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	for (size_t typeNdx = 0; typeNdx < dtypes.size(); ++typeNdx)
16805e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		builder.addType(dtypes[typeNdx], 1);
16905e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
17005e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	return builder.build(vkdi, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, /* maxSets = */ 1);
17121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
17221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
17321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang/*--------------------------------------------------------------------*//*!
17421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * \brief Create a descriptor set
17521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
17605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang * The descriptor set's layout contains the given descriptor types,
17705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang * sequentially binded to binding points starting from 0.
17821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*--------------------------------------------------------------------*/
17905e91483c6f2f48b408ed1a638cbb32468ed8dfaLei ZhangMove<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorPool pool, VkDescriptorSetLayout layout, const vector<VkDescriptorType>& dtypes, const vector<VkDescriptorBufferInfo>& descriptorInfos)
18021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
18105e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	DE_ASSERT(dtypes.size() == descriptorInfos.size());
18205e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
18368e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	const VkDescriptorSetAllocateInfo	allocInfo	=
18468e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	{
18568e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
18668e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		DE_NULL,
18768e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		pool,
18868e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		1u,
18968e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		&layout
19068e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	};
19168e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos
19268e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	Move<VkDescriptorSet>				descriptorSet	= allocateDescriptorSet(vkdi, device, &allocInfo);
19368e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	DescriptorSetUpdateBuilder			builder;
19421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
19505e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	for (deUint32 descriptorNdx = 0; descriptorNdx < dtypes.size(); ++descriptorNdx)
19605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), dtypes[descriptorNdx], &descriptorInfos[descriptorNdx]);
19721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	builder.update(vkdi, device);
19821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
19921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	return descriptorSet;
20021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
20121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
20221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang/*--------------------------------------------------------------------*//*!
20321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * \brief Create a compute pipeline based on the given shader
20421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*--------------------------------------------------------------------*/
2050e95062c203b163b84428f1e3781c0243c51bc29Lei ZhangMove<VkPipeline> createComputePipeline (const DeviceInterface& vkdi, const VkDevice& device, VkPipelineLayout pipelineLayout, VkShaderModule shader, const char* entryPoint, const vector<deUint32>& specConstants)
20621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
2070e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang	const deUint32							numSpecConstants				= (deUint32)specConstants.size();
2080e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang	vector<VkSpecializationMapEntry>		entries;
2090e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang	VkSpecializationInfo					specInfo;
2100e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang
2110e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang	if (numSpecConstants != 0)
2120e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang	{
213192b10130c346d1a713ad4e8ea71282b118c7b69Jeannot Breton		entries.resize(numSpecConstants);
2140e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang
2150e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		for (deUint32 ndx = 0; ndx < numSpecConstants; ++ndx)
2160e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		{
2170e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang			entries[ndx].constantID	= ndx;
2180e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang			entries[ndx].offset		= ndx * (deUint32)sizeof(deUint32);
2190e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang			entries[ndx].size		= sizeof(deUint32);
2200e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		}
2210e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang
2220e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		specInfo.mapEntryCount		= numSpecConstants;
2230e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		specInfo.pMapEntries		= &entries[0];
2240e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		specInfo.dataSize			= numSpecConstants * sizeof(deUint32);
2250e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		specInfo.pData				= specConstants.data();
2260e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang	}
2270e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang
22821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	const VkPipelineShaderStageCreateInfo	pipelineShaderStageCreateInfo	=
22921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	{
23021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// sType
23121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		DE_NULL,												// pNext
2320e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		(VkPipelineShaderStageCreateFlags)0,					// flags
23368e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		VK_SHADER_STAGE_COMPUTE_BIT,							// stage
2340e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		shader,													// module
2350e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		entryPoint,												// pName
2360e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		(numSpecConstants == 0) ? DE_NULL : &specInfo,			// pSpecializationInfo
23721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	};
23821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	const VkComputePipelineCreateInfo		pipelineCreateInfo				=
23921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	{
24021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// sType
24121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		DE_NULL,												// pNext
24268e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		(VkPipelineCreateFlags)0,
24321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		pipelineShaderStageCreateInfo,							// cs
24421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		pipelineLayout,											// layout
24521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		(VkPipeline)0,											// basePipelineHandle
24621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		0u,														// basePipelineIndex
24721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	};
24821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
24921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	return createComputePipeline(vkdi, device, (VkPipelineCache)0u, &pipelineCreateInfo);
25021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
25121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
25221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang/*--------------------------------------------------------------------*//*!
25321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * \brief Create a command pool
25421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *
25521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * The created command pool is designated for use on the queue type
25621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang * represented by the given queueFamilyIndex.
25721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang *//*--------------------------------------------------------------------*/
25868e7282426d639b54d15c4710d97ba97e72c76efPyry HaulosMove<VkCommandPool> createCommandPool (const DeviceInterface& vkdi, VkDevice device, deUint32 queueFamilyIndex)
25921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
260da03200a87f51bed33b3c3030ecbb6df06ff4f60Mika Isojärvi	return createCommandPool(vkdi, device, 0u, queueFamilyIndex);
26121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
26221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
26321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang} // anonymous
26421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
26521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhangnamespace vkt
26621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
26721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhangnamespace SpirVAssembly
26821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
26921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
27021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang// ComputeShaderTestCase implementations
27121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
27256f121e90ff24a88b375db1a74c296d17dd97a74Jason EkstrandSpvAsmComputeShaderCase::SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec, const ComputeTestFeatures features)
27321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	: TestCase		(testCtx, name, description)
27421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	, m_shaderSpec	(spec)
27556f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand	, m_features	(features)
27621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
27721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
27821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
27921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhangvoid SpvAsmComputeShaderCase::initPrograms (SourceCollections& programCollection) const
28021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
281d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin	programCollection.spirvAsmSources.add("compute") << m_shaderSpec.assembly.c_str() << SpirVAsmBuildOptions(m_shaderSpec.spirvVersion);
28221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
28321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
28421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei ZhangTestInstance* SpvAsmComputeShaderCase::createInstance (Context& ctx) const
28521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
286df0fcc9ad2b42210cfc8c47a9cc063d37a5261eeSlawomir Cygan	if (getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion) > ctx.getUsedApiVersion())
287d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin	{
288df0fcc9ad2b42210cfc8c47a9cc063d37a5261eeSlawomir Cygan		TCU_THROW(NotSupportedError, std::string("Vulkan higher than or equal to " + getVulkanName(getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion)) + " is required for this test to run").c_str());
289d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin	}
29056f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand	return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec, m_features);
29121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
29221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
29321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang// ComputeShaderTestInstance implementations
29421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
29556f121e90ff24a88b375db1a74c296d17dd97a74Jason EkstrandSpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec, const ComputeTestFeatures features)
2968977777244ce058cb79e1cf3b43e528322e8308cLei Zhang	: TestInstance		(ctx)
2978977777244ce058cb79e1cf3b43e528322e8308cLei Zhang	, m_shaderSpec		(spec)
2988977777244ce058cb79e1cf3b43e528322e8308cLei Zhang	, m_features		(features)
29921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
30021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
30121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
30221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhangtcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
30321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang{
30405e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	const VkPhysicalDeviceFeatures&		features			= m_context.getDeviceFeatures();
30521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
30656f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand	if ((m_features == COMPUTE_TEST_USES_INT16 || m_features == COMPUTE_TEST_USES_INT16_INT64) && !features.shaderInt16)
30756f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand	{
3088977777244ce058cb79e1cf3b43e528322e8308cLei Zhang		TCU_THROW(NotSupportedError, "shaderInt16 feature is not supported");
30956f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand	}
31056f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand
31156f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand	if ((m_features == COMPUTE_TEST_USES_INT64 || m_features == COMPUTE_TEST_USES_INT16_INT64) && !features.shaderInt64)
31256f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand	{
3138977777244ce058cb79e1cf3b43e528322e8308cLei Zhang		TCU_THROW(NotSupportedError, "shaderInt64 feature is not supported");
31456f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand	}
31556f121e90ff24a88b375db1a74c296d17dd97a74Jason Ekstrand
316c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang	{
317c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang		const InstanceInterface&			vki					= m_context.getInstanceInterface();
318c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang		const VkPhysicalDevice				physicalDevice		= m_context.getPhysicalDevice();
319c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang
320c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang		// 16bit storage features
321c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang		{
322e808b407039c05dc9822e81973a3aecb2c7dab47Alexander Galazin			if (!is16BitStorageFeaturesSupported(m_context.getUsedApiVersion(), vki, physicalDevice, m_context.getInstanceExtensions(), m_shaderSpec.requestedVulkanFeatures.ext16BitStorage))
323c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang				TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
324c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang		}
325e9eadcca906a71fd2612e51193b4f48a492fc36fEhsan Nasiri
326e9eadcca906a71fd2612e51193b4f48a492fc36fEhsan Nasiri		// VariablePointers features
327e9eadcca906a71fd2612e51193b4f48a492fc36fEhsan Nasiri		{
328e808b407039c05dc9822e81973a3aecb2c7dab47Alexander Galazin			if (!isVariablePointersFeaturesSupported(m_context.getUsedApiVersion(), vki, physicalDevice, m_context.getInstanceExtensions(), m_shaderSpec.requestedVulkanFeatures.extVariablePointers))
329e9eadcca906a71fd2612e51193b4f48a492fc36fEhsan Nasiri				TCU_THROW(NotSupportedError, "Request Variable Pointer feature not supported");
330e9eadcca906a71fd2612e51193b4f48a492fc36fEhsan Nasiri		}
331c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang	}
332c35c2901d9d604631326eec11b80b3e6b7b7d55fLei Zhang
333545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	// defer device and resource creation until after feature checks
334545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	const Unique<VkDevice>				vkDevice			(createDeviceWithExtensions(m_context, m_context.getUniversalQueueFamilyIndex(), m_context.getDeviceExtensions(), m_shaderSpec.extensions));
335545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	const VkDevice&						device				= *vkDevice;
336545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	const DeviceDriver					vkDeviceInterface	(m_context.getInstanceInterface(), device);
337545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	const DeviceInterface&				vkdi				= vkDeviceInterface;
338545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	const de::UniquePtr<vk::Allocator>	vkAllocator			(createAllocator(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), vkDeviceInterface, device));
339545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	Allocator&							allocator			= *vkAllocator;
340545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	const VkQueue						queue				(getDeviceQueue(vkDeviceInterface, device, m_context.getUniversalQueueFamilyIndex(), 0));
341545cb418b912430bce80ae69d06f669114b4211eDaniel Koch
34268e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	vector<AllocationSp>				inputAllocs;
34368e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	vector<AllocationSp>				outputAllocs;
34468e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	vector<BufferHandleSp>				inputBuffers;
34568e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	vector<BufferHandleSp>				outputBuffers;
34668e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	vector<VkDescriptorBufferInfo>		descriptorInfos;
34705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	vector<VkDescriptorType>			descriptorTypes;
34821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
34921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	DE_ASSERT(!m_shaderSpec.outputs.empty());
35021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
35121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	// Create buffer object, allocate storage, and create view for all input/output buffers.
35221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
35305e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	for (deUint32 inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx)
35421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	{
35505e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		if (m_shaderSpec.inputTypes.count(inputNdx) != 0)
35605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang			descriptorTypes.push_back(m_shaderSpec.inputTypes.at(inputNdx));
35705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		else
35805e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang			descriptorTypes.push_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
35905e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
36068e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		AllocationMp		alloc;
36168e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		const BufferSp&		input		= m_shaderSpec.inputs[inputNdx];
3620fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		vector<deUint8>		inputBytes;
3630fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi
3640fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		input->getBytes(inputBytes);
3650fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi
3660fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		const size_t		numBytes	= inputBytes.size();
36705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		BufferHandleUp*		buffer		= new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descriptorTypes.back(), allocator, numBytes, &alloc));
36821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
3690fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		setMemory(vkdi, device, &*alloc, numBytes, &inputBytes.front());
37068e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes));
37121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		inputBuffers.push_back(BufferHandleSp(buffer));
37221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		inputAllocs.push_back(de::SharedPtr<Allocation>(alloc.release()));
37321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	}
37421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
37505e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	for (deUint32 outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
37621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	{
37705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		descriptorTypes.push_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
37805e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
37968e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		AllocationMp		alloc;
38068e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		const BufferSp&		output		= m_shaderSpec.outputs[outputNdx];
3810fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		vector<deUint8>		outputBytes;
3820fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi
3830fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		output->getBytes(outputBytes);
3840fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi
3850fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		const size_t		numBytes	= outputBytes.size();
38605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		BufferHandleUp*		buffer		= new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descriptorTypes.back(), allocator, numBytes, &alloc));
38721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
3880e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang		fillMemoryWithValue(vkdi, device, &*alloc, numBytes, 0xff);
38968e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes));
39021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		outputBuffers.push_back(BufferHandleSp(buffer));
39121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang		outputAllocs.push_back(de::SharedPtr<Allocation>(alloc.release()));
39221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	}
39321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
39421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	// Create layouts and descriptor set.
39521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
39605e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	Unique<VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout(vkdi, device, descriptorTypes));
39705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	Unique<VkPipelineLayout>			pipelineLayout		(createPipelineLayout(vkdi, device, *descriptorSetLayout, m_shaderSpec.pushConstants));
39805e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	Unique<VkDescriptorPool>			descriptorPool		(createDescriptorPool(vkdi, device, descriptorTypes));
39905e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	Unique<VkDescriptorSet>				descriptorSet		(createDescriptorSet(vkdi, device, *descriptorPool, *descriptorSetLayout, descriptorTypes, descriptorInfos));
40021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
40121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	// Create compute shader and pipeline.
40221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
40368e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	const ProgramBinary&				binary				= m_context.getBinaryCollection().get("compute");
404d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin	if (m_shaderSpec.verifyBinary && !m_shaderSpec.verifyBinary(binary))
405d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin	{
406d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin		return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
407d784ada312e9c0f2d0262a87402e2ff6c6160a66Boris Zanin	}
40868e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	Unique<VkShaderModule>				module				(createShaderModule(vkdi, device, binary, (VkShaderModuleCreateFlags)0u));
40921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
4100e95062c203b163b84428f1e3781c0243c51bc29Lei Zhang	Unique<VkPipeline>					computePipeline		(createComputePipeline(vkdi, device, *pipelineLayout, *module, m_shaderSpec.entryPoint.c_str(), m_shaderSpec.specConstants));
41121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
41221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	// Create command buffer and record commands
41321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
41468e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	const Unique<VkCommandPool>			cmdPool				(createCommandPool(vkdi, device, m_context.getUniversalQueueFamilyIndex()));
415da03200a87f51bed33b3c3030ecbb6df06ff4f60Mika Isojärvi	Unique<VkCommandBuffer>				cmdBuffer			(allocateCommandBuffer(vkdi, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
41621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
41768e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	const VkCommandBufferBeginInfo		cmdBufferBeginInfo	=
41821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	{
41968e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// sType
42068e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		DE_NULL,										// pNext
42168e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
422689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos		(const VkCommandBufferInheritanceInfo*)DE_NULL,
42321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	};
42421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
42521be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	const tcu::IVec3&				numWorkGroups		= m_shaderSpec.numWorkGroups;
42621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
42721be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	VK_CHECK(vkdi.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
42821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	vkdi.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
42921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	vkdi.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
43005e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	if (m_shaderSpec.pushConstants != DE_NULL)
43105e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	{
4320fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		vector<deUint8>	pushConstantsBytes;
4330fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		m_shaderSpec.pushConstants->getBytes(pushConstantsBytes);
4340fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi
4350fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		const deUint32	size	= static_cast<deUint32>(pushConstantsBytes.size());
4360fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		const void*		data	= &pushConstantsBytes.front();
43705e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang
43805e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang		vkdi.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, /* offset = */ 0, /* size = */ size, data);
43905e91483c6f2f48b408ed1a638cbb32468ed8dfaLei Zhang	}
44021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	vkdi.cmdDispatch(*cmdBuffer, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z());
44121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	VK_CHECK(vkdi.endCommandBuffer(*cmdBuffer));
44221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
44321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	// Create fence and run.
44421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
445da03200a87f51bed33b3c3030ecbb6df06ff4f60Mika Isojärvi	const Unique<VkFence>			cmdCompleteFence	(createFence(vkdi, device));
44621be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	const deUint64					infiniteTimeout		= ~(deUint64)0u;
44768e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	const VkSubmitInfo				submitInfo			=
44868e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	{
44968e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		VK_STRUCTURE_TYPE_SUBMIT_INFO,
45068e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		DE_NULL,
45168e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		0u,
45268e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		(const VkSemaphore*)DE_NULL,
453689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos		(const VkPipelineStageFlags*)DE_NULL,
45468e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		1u,
45568e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		&cmdBuffer.get(),
45668e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		0u,
45768e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos		(const VkSemaphore*)DE_NULL,
45868e7282426d639b54d15c4710d97ba97e72c76efPyry Haulos	};
45921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
460545cb418b912430bce80ae69d06f669114b4211eDaniel Koch	VK_CHECK(vkdi.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
46121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	VK_CHECK(vkdi.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
46221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
46391459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes	// Invalidate output memory ranges before checking on host.
46491459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes	for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
46591459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes	{
4660fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi		invalidateMemory(vkdi, device, outputAllocs[outputNdx].get(), m_shaderSpec.outputs[outputNdx]->getByteSize());
46791459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes	}
46891459cb30edf4ea279715f11e5aad57cfd6d94aaTim Hughes
46921be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	// Check output.
470cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyn	if (m_shaderSpec.verifyIO)
47121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	{
472497e62d7dc5c1ae90c977e2c0037c1aae6000831Csaba Osztrogonác		if (!(*m_shaderSpec.verifyIO)(m_shaderSpec.inputs, outputAllocs, m_shaderSpec.outputs, m_context.getTestContext().getLog()))
473e47e81cda3ab7215d6089f4f5f631fa4f4385e10Jason Ekstrand			return tcu::TestStatus(m_shaderSpec.failResult, m_shaderSpec.failMessage);
47421be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang	}
475cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyn	else
476cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyn	{
477cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyn		for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
478cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyn		{
4790fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi			const BufferSp&	expectedOutput = m_shaderSpec.outputs[outputNdx];
4800fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi			vector<deUint8>	expectedBytes;
4810fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi
4820fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi			expectedOutput->getBytes(expectedBytes);
4830fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi
4840fe7f04e2aefb289e052e82f71ab8d2a1f41dd76Paavo Pessi			if (deMemCmp(&expectedBytes.front(), outputAllocs[outputNdx]->getHostPtr(), expectedBytes.size()))
485e47e81cda3ab7215d6089f4f5f631fa4f4385e10Jason Ekstrand				return tcu::TestStatus(m_shaderSpec.failResult, m_shaderSpec.failMessage);
486cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyn		}
487cc54b9c0f4b04cd3e3b9051c22c368e68a5e134fAndrew Woloszyn	}
48821be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
489e47e81cda3ab7215d6089f4f5f631fa4f4385e10Jason Ekstrand	return tcu::TestStatus::pass("Output match with expected");
49021be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang}
49121be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang
49221be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang} // SpirVAssembly
49321be639ab35b03f6d4d05e11fe662a7dd6bfee2bLei Zhang} // vkt
494