1fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski/*------------------------------------------------------------------------
2fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski * Vulkan Conformance Tests
3fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski * ------------------------
4fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski *
59a869c2848d0419008cb99f72c9fa372e3af805dPyry Haulos * Copyright (c) 2016 The Khronos Group Inc.
6c05b7f1437e619205c96eaa31c0b79ec97a0d47dPyry Haulos * Copyright (c) 2016 The Android Open Source Project
7fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski *
8978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * Licensed under the Apache License, Version 2.0 (the "License");
9978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * you may not use this file except in compliance with the License.
10978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * You may obtain a copy of the License at
11fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski *
12978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos *      http://www.apache.org/licenses/LICENSE-2.0
13fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski *
14978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * Unless required by applicable law or agreed to in writing, software
15978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * distributed under the License is distributed on an "AS IS" BASIS,
16978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * See the License for the specific language governing permissions and
18978d3d585aa549eb1e729b51e9d85fc6477240f9Pyry Haulos * limitations under the License.
19fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski *
20fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski *//*!
21fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski * \file
22fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski * \brief Indirect Compute Dispatch tests
23fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski *//*--------------------------------------------------------------------*/
24fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
25fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vktComputeIndirectComputeDispatchTests.hpp"
26956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski#include "vktComputeTestsUtil.hpp"
27fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
28fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include <string>
29fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include <map>
30fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include <vector>
31fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
32fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vkDefs.hpp"
33fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vkRef.hpp"
34fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vkRefUtil.hpp"
35fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vktTestCase.hpp"
36fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vktTestCaseUtil.hpp"
37fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vkPlatform.hpp"
38fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vkPrograms.hpp"
39fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vkMemUtil.hpp"
40fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vkBuilderUtil.hpp"
41fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "vkQueryUtil.hpp"
42fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
43fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "tcuVector.hpp"
44fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "tcuVectorUtil.hpp"
45fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "tcuTestLog.hpp"
46fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "tcuRGBA.hpp"
47fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "tcuStringTemplate.hpp"
48fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
49fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "deUniquePtr.hpp"
50fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "deSharedPtr.hpp"
51fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "deStringUtil.hpp"
52fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "deArrayUtil.hpp"
53fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
54fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski#include "gluShaderUtil.hpp"
55fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
56fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskinamespace vkt
57fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
58fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskinamespace compute
59fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
60956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowskinamespace
61956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski{
62fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
6349c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulosenum
6449c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos{
6549c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos	RESULT_BLOCK_BASE_SIZE			= 4 * (int)sizeof(deUint32), // uvec3 + uint
6649c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos	RESULT_BLOCK_NUM_PASSED_OFFSET	= 3 * (int)sizeof(deUint32),
6749c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos	INDIRECT_COMMAND_OFFSET			= 3 * (int)sizeof(deUint32),
6849c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos};
69fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
70956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowskivk::VkDeviceSize getResultBlockAlignedSize (const vk::InstanceInterface&	instance_interface,
71956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski											const vk::VkPhysicalDevice		physicalDevice,
72956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski											const vk::VkDeviceSize			baseSize)
73956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski{
74956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	// TODO getPhysicalDeviceProperties() was added to vkQueryUtil in 41-image-load-store-tests. Use it once it's merged.
75956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	vk::VkPhysicalDeviceProperties deviceProperties;
76956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	instance_interface.getPhysicalDeviceProperties(physicalDevice, &deviceProperties);
77956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	vk::VkDeviceSize alignment = deviceProperties.limits.minStorageBufferOffsetAlignment;
78956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski
79956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	if (alignment == 0 || (baseSize % alignment == 0))
80956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		return baseSize;
81956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	else
82956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		return (baseSize / alignment + 1)*alignment;
83956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski}
84956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski
85fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskistruct DispatchCommand
86fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
87fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski				DispatchCommand (const deIntptr		offset,
88fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski								 const tcu::UVec3&	numWorkGroups)
89fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski					: m_offset			(offset)
90fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski					, m_numWorkGroups	(numWorkGroups) {}
91fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
92fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	deIntptr	m_offset;
93fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	tcu::UVec3	m_numWorkGroups;
94fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski};
95fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
96fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskitypedef std::vector<DispatchCommand> DispatchCommandsVec;
97fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
98fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskistruct DispatchCaseDesc
99fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
100fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski								DispatchCaseDesc (const char*					name,
101fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski												  const char*					description,
102fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski												  const deUintptr				bufferSize,
103fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski												  const tcu::UVec3				workGroupSize,
104fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski												  const DispatchCommandsVec&	dispatchCommands)
105fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski									: m_name				(name)
106fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski									, m_description			(description)
107fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski									, m_bufferSize			(bufferSize)
108fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski									, m_workGroupSize		(workGroupSize)
109fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski									, m_dispatchCommands	(dispatchCommands) {}
110fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
111fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const char*					m_name;
112fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const char*					m_description;
113fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const deUintptr				m_bufferSize;
114fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const tcu::UVec3			m_workGroupSize;
115fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const DispatchCommandsVec	m_dispatchCommands;
116fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski};
117fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
118fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiclass IndirectDispatchInstanceBufferUpload : public vkt::TestInstance
119fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
120fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskipublic:
121fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski									IndirectDispatchInstanceBufferUpload	(Context&					context,
122fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			 const std::string&			name,
123fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			 const deUintptr			bufferSize,
124fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			 const tcu::UVec3&			workGroupSize,
125fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			 const DispatchCommandsVec& dispatchCommands);
126fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
127fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	virtual							~IndirectDispatchInstanceBufferUpload	(void) {}
128fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
129fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	virtual tcu::TestStatus			iterate									(void);
130fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
131fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiprotected:
132956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	virtual void					fillIndirectBufferData					(const vk::VkCommandBuffer	commandBuffer,
133956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski																			 const Buffer&				indirectBuffer);
134fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
135956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	deBool							verifyResultBuffer						(const Buffer&				resultBuffer,
136956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski																			 const vk::VkDeviceSize		resultBlockSize,
137956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski																			 const vk::VkDeviceSize		resultBufferSize) const;
138fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
139fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	Context&						m_context;
140fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const std::string				m_name;
141fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
142fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const vk::DeviceInterface&		m_device_interface;
143fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const vk::VkDevice				m_device;
144fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
145fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const vk::VkQueue				m_queue;
146fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const deUint32					m_queueFamilyIndex;
147fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
148fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const deUintptr					m_bufferSize;
149fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const tcu::UVec3				m_workGroupSize;
150fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const DispatchCommandsVec		m_dispatchCommands;
151fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
152fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	vk::Allocator&					m_allocator;
153fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
154fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiprivate:
155fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchInstanceBufferUpload (const vkt::TestInstance&);
156fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchInstanceBufferUpload& operator= (const vkt::TestInstance&);
157fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski};
158fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
159fcc71113e2a063a770310435bff4be7984c86f02Maciej JesionowskiIndirectDispatchInstanceBufferUpload::IndirectDispatchInstanceBufferUpload (Context&					context,
160fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			const std::string&			name,
161fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			const deUintptr				bufferSize,
162fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			const tcu::UVec3&			workGroupSize,
163fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			const DispatchCommandsVec&	dispatchCommands)
164fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	: vkt::TestInstance		(context)
165fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_context				(context)
166fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_name				(name)
167fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_device_interface	(context.getDeviceInterface())
168fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_device				(context.getDevice())
169fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_queue				(context.getUniversalQueue())
170fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
171fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_bufferSize			(bufferSize)
172fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_workGroupSize		(workGroupSize)
173fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_dispatchCommands	(dispatchCommands)
1747c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	, m_allocator			(context.getDefaultAllocator())
175fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
176fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
177fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
178956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowskivoid IndirectDispatchInstanceBufferUpload::fillIndirectBufferData (const vk::VkCommandBuffer commandBuffer, const Buffer& indirectBuffer)
179fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
1807c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	DE_UNREF(commandBuffer);
1817c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski
182956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::Allocation& alloc = indirectBuffer.getAllocation();
183956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	deUint8* indirectDataPtr = reinterpret_cast<deUint8*>(alloc.getHostPtr());
184fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
185fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	for (DispatchCommandsVec::const_iterator cmdIter = m_dispatchCommands.begin(); cmdIter != m_dispatchCommands.end(); ++cmdIter)
186fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
187fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		DE_ASSERT(cmdIter->m_offset >= 0);
188fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		DE_ASSERT(cmdIter->m_offset % sizeof(deUint32) == 0);
18949c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos		DE_ASSERT(cmdIter->m_offset + INDIRECT_COMMAND_OFFSET <= (deIntptr)m_bufferSize);
190fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
191fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		deUint32* const dstPtr = (deUint32*)&indirectDataPtr[cmdIter->m_offset];
192fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
193fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		dstPtr[0] = cmdIter->m_numWorkGroups[0];
194fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		dstPtr[1] = cmdIter->m_numWorkGroups[1];
195fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		dstPtr[2] = cmdIter->m_numWorkGroups[2];
196fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	}
197fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
198956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	vk::flushMappedMemoryRange(m_device_interface, m_device, alloc.getMemory(), alloc.getOffset(), m_bufferSize);
199fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
200fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
201fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskitcu::TestStatus IndirectDispatchInstanceBufferUpload::iterate (void)
202fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
203fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	tcu::TestContext& testCtx = m_context.getTestContext();
204fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
205fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	testCtx.getLog() << tcu::TestLog::Message << "GL_DISPATCH_INDIRECT_BUFFER size = " << m_bufferSize << tcu::TestLog::EndMessage;
206fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
207fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		tcu::ScopedLogSection section(testCtx.getLog(), "Commands", "Indirect Dispatch Commands (" + de::toString(m_dispatchCommands.size()) + " in total)");
208fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
209fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		for (deUint32 cmdNdx = 0; cmdNdx < m_dispatchCommands.size(); ++cmdNdx)
210fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		{
211fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski			testCtx.getLog()
212fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski				<< tcu::TestLog::Message
213fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski				<< cmdNdx << ": " << "offset = " << m_dispatchCommands[cmdNdx].m_offset << ", numWorkGroups = " << m_dispatchCommands[cmdNdx].m_numWorkGroups
214fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski				<< tcu::TestLog::EndMessage;
215fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		}
216fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	}
217fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
218fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create result buffer
21949c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos	const vk::VkDeviceSize resultBlockSize = getResultBlockAlignedSize(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), RESULT_BLOCK_BASE_SIZE);
220956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::VkDeviceSize resultBufferSize = resultBlockSize * (deUint32)m_dispatchCommands.size();
221fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
222956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	Buffer resultBuffer(
223956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		m_device_interface, m_device, m_allocator,
224956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		makeBufferCreateInfo(resultBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
225956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		vk::MemoryRequirement::HostVisible);
226fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
227fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
228956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		const vk::Allocation& alloc = resultBuffer.getAllocation();
229956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		deUint8* resultDataPtr = reinterpret_cast<deUint8*>(alloc.getHostPtr());
230fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
231956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		for (deUint32 cmdNdx = 0; cmdNdx < m_dispatchCommands.size(); ++cmdNdx)
232956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		{
233956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski			deUint8* const	dstPtr = &resultDataPtr[resultBlockSize*cmdNdx];
234956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski
235956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski			*(deUint32*)(dstPtr + 0 * sizeof(deUint32)) = m_dispatchCommands[cmdNdx].m_numWorkGroups[0];
236956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski			*(deUint32*)(dstPtr + 1 * sizeof(deUint32)) = m_dispatchCommands[cmdNdx].m_numWorkGroups[1];
237956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski			*(deUint32*)(dstPtr + 2 * sizeof(deUint32)) = m_dispatchCommands[cmdNdx].m_numWorkGroups[2];
23849c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos			*(deUint32*)(dstPtr + RESULT_BLOCK_NUM_PASSED_OFFSET) = 0;
239956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		}
240956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski
241956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		vk::flushMappedMemoryRange(m_device_interface, m_device, alloc.getMemory(), alloc.getOffset(), resultBufferSize);
242fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	}
243fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
244fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create verify compute shader
245956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::Unique<vk::VkShaderModule> verifyShader(createShaderModule(
246956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		m_device_interface, m_device, m_context.getBinaryCollection().get("indirect_dispatch_" + m_name + "_verify"), 0u));
247fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
248fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create descriptorSetLayout
249fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	vk::DescriptorSetLayoutBuilder layoutBuilder;
250fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2517c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(m_device_interface, m_device));
252fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
253fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create compute pipeline
254956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(m_device_interface, m_device, *descriptorSetLayout));
255956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::Unique<vk::VkPipeline> computePipeline(makeComputePipeline(m_device_interface, m_device, *pipelineLayout, *verifyShader));
256fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
257fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create descriptor pool
258956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::Unique<vk::VkDescriptorPool> descriptorPool(
259956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		vk::DescriptorPoolBuilder()
260f4c9b6c3fb7ab1eaab7718f80408b62ff5430c1fpflisiko		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, (deUint32)m_dispatchCommands.size())
261956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		.build(m_device_interface, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, static_cast<deUint32>(m_dispatchCommands.size())));
262fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
263956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::VkBufferMemoryBarrier ssboPostBarrier = makeBufferMemoryBarrier(
264956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSize);
265fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
266fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create command buffer
267956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(m_device_interface, m_device, m_queueFamilyIndex));
26855dd4426673bd260dde56addcfea802f21c31304Mika Isojärvi	const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(m_device_interface, m_device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
269fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
270fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Begin recording commands
271956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	beginCommandBuffer(m_device_interface, *cmdBuffer);
272fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
273fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create indirect buffer
274956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	Buffer indirectBuffer(
275956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		m_device_interface, m_device, m_allocator,
276956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		makeBufferCreateInfo(m_bufferSize, vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
277956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		vk::MemoryRequirement::HostVisible);
278956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	fillIndirectBufferData(*cmdBuffer, indirectBuffer);
279fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
280fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Bind compute pipeline
281956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	m_device_interface.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
282fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
283fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Allocate descriptor sets
28449e0fed2d19130bc11ad400d6c1eb28d12bcb9c7Maciej Jesionowski	typedef de::SharedPtr<vk::Unique<vk::VkDescriptorSet> > SharedVkDescriptorSet;
28549e0fed2d19130bc11ad400d6c1eb28d12bcb9c7Maciej Jesionowski	std::vector<SharedVkDescriptorSet> descriptorSets(m_dispatchCommands.size());
286fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
287fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	vk::VkDeviceSize curOffset = 0;
288fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
289fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create descriptor sets
290fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	for (deUint32 cmdNdx = 0; cmdNdx < m_dispatchCommands.size(); ++cmdNdx)
291fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
29249e0fed2d19130bc11ad400d6c1eb28d12bcb9c7Maciej Jesionowski		descriptorSets[cmdNdx] = SharedVkDescriptorSet(new vk::Unique<vk::VkDescriptorSet>(
29349e0fed2d19130bc11ad400d6c1eb28d12bcb9c7Maciej Jesionowski									makeDescriptorSet(m_device_interface, m_device, *descriptorPool, *descriptorSetLayout)));
294fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
295956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		const vk::VkDescriptorBufferInfo resultDescriptorInfo = makeDescriptorBufferInfo(*resultBuffer, curOffset, resultBlockSize);
296956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski
297956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		vk::DescriptorSetUpdateBuilder descriptorSetBuilder;
29849e0fed2d19130bc11ad400d6c1eb28d12bcb9c7Maciej Jesionowski		descriptorSetBuilder.writeSingle(**descriptorSets[cmdNdx], vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo);
299fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		descriptorSetBuilder.update(m_device_interface, m_device);
300fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
301fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		// Bind descriptor set
30249e0fed2d19130bc11ad400d6c1eb28d12bcb9c7Maciej Jesionowski		m_device_interface.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &(**descriptorSets[cmdNdx]), 0u, DE_NULL);
303fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
304fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		// Dispatch indirect compute command
305956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		m_device_interface.cmdDispatchIndirect(*cmdBuffer, *indirectBuffer, m_dispatchCommands[cmdNdx].m_offset);
306fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
307fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		curOffset += resultBlockSize;
308fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	}
309fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
310fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Insert memory barrier
311689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos	m_device_interface.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0,
312689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos										  0, (const vk::VkMemoryBarrier*)DE_NULL,
313689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos										  1, &ssboPostBarrier,
314689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos										  0, (const vk::VkImageMemoryBarrier*)DE_NULL);
315fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
316fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// End recording commands
317956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	endCommandBuffer(m_device_interface, *cmdBuffer);
318fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
319fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Wait for command buffer execution finish
320956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	submitCommandsAndWait(m_device_interface, m_device, m_queue, *cmdBuffer);
321fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
322fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Check if result buffer contains valid values
323fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	if (verifyResultBuffer(resultBuffer, resultBlockSize, resultBufferSize))
324fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Pass");
325fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	else
326fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Invalid values in result buffer");
327fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
328fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
329956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej JesionowskideBool IndirectDispatchInstanceBufferUpload::verifyResultBuffer (const Buffer&			resultBuffer,
330956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski																 const vk::VkDeviceSize	resultBlockSize,
331956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski																 const vk::VkDeviceSize	resultBufferSize) const
332fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
333fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	deBool allOk = true;
334956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::Allocation& alloc = resultBuffer.getAllocation();
335956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	vk::invalidateMappedMemoryRange(m_device_interface, m_device, alloc.getMemory(), alloc.getOffset(), resultBufferSize);
336956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski
337956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const deUint8* const resultDataPtr = reinterpret_cast<deUint8*>(alloc.getHostPtr());
338fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
339fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	for (deUint32 cmdNdx = 0; cmdNdx < m_dispatchCommands.size(); cmdNdx++)
340fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
341fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		const DispatchCommand&	cmd = m_dispatchCommands[cmdNdx];
342fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		const deUint8* const	srcPtr = (const deUint8*)resultDataPtr + cmdNdx*resultBlockSize;
34349c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos		const deUint32			numPassed = *(const deUint32*)(srcPtr + RESULT_BLOCK_NUM_PASSED_OFFSET);
344fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		const deUint32			numInvocationsPerGroup = m_workGroupSize[0] * m_workGroupSize[1] * m_workGroupSize[2];
345fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		const deUint32			numGroups = cmd.m_numWorkGroups[0] * cmd.m_numWorkGroups[1] * cmd.m_numWorkGroups[2];
346fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		const deUint32			expectedCount = numInvocationsPerGroup * numGroups;
347fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
348fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		if (numPassed != expectedCount)
349fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		{
350fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski			tcu::TestContext& testCtx = m_context.getTestContext();
351fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
352fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski			testCtx.getLog()
353fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski				<< tcu::TestLog::Message
354fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski				<< "ERROR: got invalid result for invocation " << cmdNdx
355fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski				<< ": got numPassed = " << numPassed << ", expected " << expectedCount
356fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski				<< tcu::TestLog::EndMessage;
357fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
358fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski			allOk = false;
359fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		}
360fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	}
361fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
362fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	return allOk;
363fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
364fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
365fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiclass IndirectDispatchCaseBufferUpload : public vkt::TestCase
366fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
367fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskipublic:
368fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski								IndirectDispatchCaseBufferUpload	(tcu::TestContext&			testCtx,
369fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																	 const DispatchCaseDesc&	caseDesc,
370fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																	 const glu::GLSLVersion		glslVersion);
371fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
372fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	virtual						~IndirectDispatchCaseBufferUpload	(void) {}
373fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
374956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	virtual void				initPrograms						(vk::SourceCollections&		programCollection) const;
375956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	virtual TestInstance*		createInstance						(Context&					context) const;
376fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
377fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiprotected:
378fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const deUintptr				m_bufferSize;
379fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const tcu::UVec3			m_workGroupSize;
380fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const DispatchCommandsVec	m_dispatchCommands;
381fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const glu::GLSLVersion		m_glslVersion;
382fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
383fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiprivate:
384fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchCaseBufferUpload (const vkt::TestCase&);
385fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchCaseBufferUpload& operator= (const vkt::TestCase&);
386fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski};
387fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
388fcc71113e2a063a770310435bff4be7984c86f02Maciej JesionowskiIndirectDispatchCaseBufferUpload::IndirectDispatchCaseBufferUpload (tcu::TestContext&		testCtx,
389fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																	const DispatchCaseDesc& caseDesc,
390fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																	const glu::GLSLVersion	glslVersion)
391fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	: vkt::TestCase			(testCtx, caseDesc.m_name, caseDesc.m_description)
392fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_bufferSize			(caseDesc.m_bufferSize)
393fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_workGroupSize		(caseDesc.m_workGroupSize)
394fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_dispatchCommands	(caseDesc.m_dispatchCommands)
395fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	, m_glslVersion			(glslVersion)
396fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
397fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
398fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
399fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskivoid IndirectDispatchCaseBufferUpload::initPrograms (vk::SourceCollections& programCollection) const
400fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
401fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const char* const	versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
402fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
403fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	std::ostringstream	verifyBuffer;
404fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
405fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	verifyBuffer
406fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< versionDecl << "\n"
407fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "layout(local_size_x = ${LOCAL_SIZE_X}, local_size_y = ${LOCAL_SIZE_Y}, local_size_z = ${LOCAL_SIZE_Z}) in;\n"
408fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "layout(set = 0, binding = 0, std430) buffer Result\n"
409fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "{\n"
410fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "    uvec3           expectedGroupCount;\n"
411fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "    coherent uint   numPassed;\n"
412fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "} result;\n"
413fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "void main (void)\n"
414fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "{\n"
415fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "    if (all(equal(result.expectedGroupCount, gl_NumWorkGroups)))\n"
416fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "        atomicAdd(result.numPassed, 1u);\n"
417fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "}\n";
418fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
419fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	std::map<std::string, std::string> args;
420fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
421fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	args["LOCAL_SIZE_X"] = de::toString(m_workGroupSize.x());
422fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	args["LOCAL_SIZE_Y"] = de::toString(m_workGroupSize.y());
423fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	args["LOCAL_SIZE_Z"] = de::toString(m_workGroupSize.z());
424fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
425fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	std::string verifyProgramString = tcu::StringTemplate(verifyBuffer.str()).specialize(args);
426fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
427fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	programCollection.glslSources.add("indirect_dispatch_" + m_name + "_verify") << glu::ComputeSource(verifyProgramString);
428fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
429fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
430fcc71113e2a063a770310435bff4be7984c86f02Maciej JesionowskiTestInstance* IndirectDispatchCaseBufferUpload::createInstance (Context& context) const
431fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
432fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	return new IndirectDispatchInstanceBufferUpload(context, m_name, m_bufferSize, m_workGroupSize, m_dispatchCommands);
433fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
434fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
435fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiclass IndirectDispatchInstanceBufferGenerate : public IndirectDispatchInstanceBufferUpload
436fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
437fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskipublic:
438fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski									IndirectDispatchInstanceBufferGenerate	(Context&					context,
439fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			 const std::string&			name,
440fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			 const deUintptr			bufferSize,
441fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			 const tcu::UVec3&			workGroupSize,
442fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																			 const DispatchCommandsVec&	dispatchCommands)
443956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski										: IndirectDispatchInstanceBufferUpload(context, name, bufferSize, workGroupSize, dispatchCommands) {}
444fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
445fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	virtual							~IndirectDispatchInstanceBufferGenerate	(void) {}
446fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
447fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiprotected:
448956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	virtual void					fillIndirectBufferData					(const vk::VkCommandBuffer	commandBuffer,
449956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski																			 const Buffer&				indirectBuffer);
450fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
451fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	vk::Move<vk::VkDescriptorPool>	m_descriptorPool;
452fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	vk::Move<vk::VkDescriptorSet>	m_descriptorSet;
453956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	vk::Move<vk::VkPipelineLayout>	m_pipelineLayout;
454956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	vk::Move<vk::VkPipeline>		m_computePipeline;
455fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
456fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiprivate:
457fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchInstanceBufferGenerate (const vkt::TestInstance&);
458fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchInstanceBufferGenerate& operator= (const vkt::TestInstance&);
459fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski};
460fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
461956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowskivoid IndirectDispatchInstanceBufferGenerate::fillIndirectBufferData (const vk::VkCommandBuffer commandBuffer, const Buffer& indirectBuffer)
462fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
463fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create compute shader that generates data for indirect buffer
464956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::Unique<vk::VkShaderModule> genIndirectBufferDataShader(createShaderModule(
465956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		m_device_interface, m_device, m_context.getBinaryCollection().get("indirect_dispatch_" + m_name + "_generate"), 0u));
466fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
467fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create descriptorSetLayout
468fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	vk::DescriptorSetLayoutBuilder layoutBuilder;
469fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4707c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(m_device_interface, m_device));
471fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
472fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create compute pipeline
473956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	m_pipelineLayout = makePipelineLayout(m_device_interface, m_device, *descriptorSetLayout);
474956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	m_computePipeline = makeComputePipeline(m_device_interface, m_device, *m_pipelineLayout, *genIndirectBufferDataShader);
475fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
476fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create descriptor pool
477fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	m_descriptorPool = vk::DescriptorPoolBuilder()
478956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
479956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		.build(m_device_interface, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
480fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
481fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Create descriptor set
482956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	m_descriptorSet = makeDescriptorSet(m_device_interface, m_device, *m_descriptorPool, *descriptorSetLayout);
483fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
484956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::VkDescriptorBufferInfo indirectDescriptorInfo = makeDescriptorBufferInfo(*indirectBuffer, 0ull, m_bufferSize);
485fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
486fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	vk::DescriptorSetUpdateBuilder	descriptorSetBuilder;
487fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	descriptorSetBuilder.writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indirectDescriptorInfo);
488fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	descriptorSetBuilder.update(m_device_interface, m_device);
489fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
490956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	const vk::VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(
491956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski		vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT, *indirectBuffer, 0ull, m_bufferSize);
492956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski
493fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Bind compute pipeline
494956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	m_device_interface.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
495fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
496fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Bind descriptor set
497956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	m_device_interface.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
498fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
499fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Dispatch compute command
500956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	m_device_interface.cmdDispatch(commandBuffer, 1u, 1u, 1u);
501fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
502fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Insert memory barrier
503689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos	m_device_interface.cmdPipelineBarrier(commandBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, (vk::VkDependencyFlags)0,
504689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos										  0, (const vk::VkMemoryBarrier*)DE_NULL,
505689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos										  1, &bufferBarrier,
506689c095f881a410da6a315795452a8e00ad95a9dPyry Haulos										  0, (const vk::VkImageMemoryBarrier*)DE_NULL);
507fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
508fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
509fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiclass IndirectDispatchCaseBufferGenerate : public IndirectDispatchCaseBufferUpload
510fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
511fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskipublic:
512956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski							IndirectDispatchCaseBufferGenerate	(tcu::TestContext&			testCtx,
513fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski																 const DispatchCaseDesc&	caseDesc,
514956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski																 const glu::GLSLVersion		glslVersion)
515fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski								: IndirectDispatchCaseBufferUpload(testCtx, caseDesc, glslVersion) {}
516fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
517fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	virtual					~IndirectDispatchCaseBufferGenerate	(void) {}
518fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
519956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	virtual void			initPrograms						(vk::SourceCollections&		programCollection) const;
520956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski	virtual TestInstance*	createInstance						(Context&					context) const;
521fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
522fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskiprivate:
523fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchCaseBufferGenerate (const vkt::TestCase&);
524fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchCaseBufferGenerate& operator= (const vkt::TestCase&);
525fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski};
526fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
527fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskivoid IndirectDispatchCaseBufferGenerate::initPrograms (vk::SourceCollections& programCollection) const
528fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
529fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	IndirectDispatchCaseBufferUpload::initPrograms(programCollection);
530fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
531fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	const char* const	versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
532fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
533fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	std::ostringstream computeBuffer;
534fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
535fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Header
536fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	computeBuffer
537fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< versionDecl << "\n"
538fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
539fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "layout(set = 0, binding = 0, std430) buffer Out\n"
540fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "{\n"
541fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "	highp uint data[];\n"
542fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "};\n"
543fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "void writeCmd (uint offset, uvec3 numWorkGroups)\n"
544fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "{\n"
545fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "	data[offset+0u] = numWorkGroups.x;\n"
546fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "	data[offset+1u] = numWorkGroups.y;\n"
547fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "	data[offset+2u] = numWorkGroups.z;\n"
548fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "}\n"
549fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "void main (void)\n"
550fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		<< "{\n";
551fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
552fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Dispatch commands
553fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	for (DispatchCommandsVec::const_iterator cmdIter = m_dispatchCommands.begin(); cmdIter != m_dispatchCommands.end(); ++cmdIter)
554fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
555fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		const deUint32 offs = (deUint32)(cmdIter->m_offset / sizeof(deUint32));
556a9f670634b3213102e5d230bc5f72c40228cdf13Pyry Haulos		DE_ASSERT((size_t)offs * sizeof(deUint32) == (size_t)cmdIter->m_offset);
557fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
558fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		computeBuffer
559fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski			<< "\twriteCmd(" << offs << "u, uvec3("
560fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski			<< cmdIter->m_numWorkGroups.x() << "u, "
561fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski			<< cmdIter->m_numWorkGroups.y() << "u, "
562fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski			<< cmdIter->m_numWorkGroups.z() << "u));\n";
563fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	}
564fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
565fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	// Ending
566fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	computeBuffer << "}\n";
567fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
568fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	std::string computeString = computeBuffer.str();
569fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
570fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	programCollection.glslSources.add("indirect_dispatch_" + m_name + "_generate") << glu::ComputeSource(computeString);
571fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
572fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
573fcc71113e2a063a770310435bff4be7984c86f02Maciej JesionowskiTestInstance* IndirectDispatchCaseBufferGenerate::createInstance (Context& context) const
574fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
575fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	return new IndirectDispatchInstanceBufferGenerate(context, m_name, m_bufferSize, m_workGroupSize, m_dispatchCommands);
576fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
577fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
5787c07a7d482295107670797fdf7da8a40e461b40bMaciej JesionowskiDispatchCommandsVec commandsVec (const DispatchCommand& cmd)
5797c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski{
5807c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	DispatchCommandsVec vec;
5817c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd);
5827c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	return vec;
5837c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski}
5847c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski
5857c07a7d482295107670797fdf7da8a40e461b40bMaciej JesionowskiDispatchCommandsVec commandsVec (const DispatchCommand& cmd0,
5867c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd1,
5877c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd2,
5887c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd3,
5897c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd4)
5907c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski{
5917c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	DispatchCommandsVec vec;
5927c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd0);
5937c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd1);
5947c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd2);
5957c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd3);
5967c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd4);
5977c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	return vec;
5987c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski}
5997c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski
6007c07a7d482295107670797fdf7da8a40e461b40bMaciej JesionowskiDispatchCommandsVec commandsVec (const DispatchCommand& cmd0,
6017c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd1,
6027c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd2,
6037c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd3,
6047c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd4,
6057c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd5,
6067c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski								 const DispatchCommand& cmd6)
6077c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski{
6087c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	DispatchCommandsVec vec;
6097c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd0);
6107c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd1);
6117c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd2);
6127c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd3);
6137c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd4);
6147c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd5);
6157c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	vec.push_back(cmd6);
6167c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski	return vec;
6177c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski}
6187c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski
619956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski} // anonymous ns
620956dc48a6649925e468ba4f4f1ce6cd7591472ddMaciej Jesionowski
621fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowskitcu::TestCaseGroup* createIndirectComputeDispatchTests (tcu::TestContext& testCtx)
622fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski{
623fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	static const DispatchCaseDesc s_dispatchCases[] =
624fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
62549c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos		DispatchCaseDesc("single_invocation", "Single invocation only from offset 0", INDIRECT_COMMAND_OFFSET, tcu::UVec3(1, 1, 1),
6267c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand(0, tcu::UVec3(1, 1, 1)))
6277c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski        ),
62849c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos		DispatchCaseDesc("multiple_groups", "Multiple groups dispatched from offset 0", INDIRECT_COMMAND_OFFSET, tcu::UVec3(1, 1, 1),
6297c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand(0, tcu::UVec3(2, 3, 5)))
6307c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski		),
63149c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos		DispatchCaseDesc("multiple_groups_multiple_invocations", "Multiple groups of size 2x3x1 from offset 0", INDIRECT_COMMAND_OFFSET, tcu::UVec3(2, 3, 1),
6327c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand(0, tcu::UVec3(1, 2, 3)))
6337c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski		),
63449c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos		DispatchCaseDesc("small_offset", "Small offset", 16 + INDIRECT_COMMAND_OFFSET, tcu::UVec3(1, 1, 1),
6357c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand(16, tcu::UVec3(1, 1, 1)))
6367c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski		),
637fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		DispatchCaseDesc("large_offset", "Large offset", (2 << 20), tcu::UVec3(1, 1, 1),
6387c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand((1 << 20) + 12, tcu::UVec3(1, 1, 1)))
6397c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski		),
640fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		DispatchCaseDesc("large_offset_multiple_invocations", "Large offset, multiple invocations", (2 << 20), tcu::UVec3(2, 3, 1),
6417c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand((1 << 20) + 12, tcu::UVec3(1, 2, 3)))
6427c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski		),
64349c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos		DispatchCaseDesc("empty_command", "Empty command", INDIRECT_COMMAND_OFFSET, tcu::UVec3(1, 1, 1),
6447c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand(0, tcu::UVec3(0, 0, 0)))
6457c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski		),
646fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		DispatchCaseDesc("multi_dispatch", "Dispatch multiple compute commands from single buffer", 1 << 10, tcu::UVec3(3, 1, 2),
6477c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand(0, tcu::UVec3(1, 1, 1)),
64849c4f4f532ad8094b5de6fc6e2ec1c77db4066ccPyry Haulos						DispatchCommand(INDIRECT_COMMAND_OFFSET, tcu::UVec3(2, 1, 1)),
6497c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(104, tcu::UVec3(1, 3, 1)),
6507c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(40, tcu::UVec3(1, 1, 7)),
6517c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(52, tcu::UVec3(1, 1, 4)))
6527c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski		),
653fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		DispatchCaseDesc("multi_dispatch_reuse_command", "Dispatch multiple compute commands from single buffer", 1 << 10, tcu::UVec3(3, 1, 2),
6547c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski			commandsVec(DispatchCommand(0, tcu::UVec3(1, 1, 1)),
6557c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(0, tcu::UVec3(1, 1, 1)),
6567c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(0, tcu::UVec3(1, 1, 1)),
6577c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(104, tcu::UVec3(1, 3, 1)),
6587c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(104, tcu::UVec3(1, 3, 1)),
6597c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(52, tcu::UVec3(1, 1, 4)),
6607c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski						DispatchCommand(52, tcu::UVec3(1, 1, 4)))
6617c07a7d482295107670797fdf7da8a40e461b40bMaciej Jesionowski		),
662fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	};
663fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
664fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> indirectComputeDispatchTests(new tcu::TestCaseGroup(testCtx, "indirect_dispatch", "Indirect dispatch tests"));
665fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
666fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	tcu::TestCaseGroup* const	groupBufferUpload = new tcu::TestCaseGroup(testCtx, "upload_buffer", "");
667fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	indirectComputeDispatchTests->addChild(groupBufferUpload);
668fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
669fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_dispatchCases); ndx++)
670fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
671fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		groupBufferUpload->addChild(new IndirectDispatchCaseBufferUpload(testCtx, s_dispatchCases[ndx], glu::GLSL_VERSION_310_ES));
672fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	}
673fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
674fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	tcu::TestCaseGroup* const	groupBufferGenerate = new tcu::TestCaseGroup(testCtx, "gen_in_compute", "");
675fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	indirectComputeDispatchTests->addChild(groupBufferGenerate);
676fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
677fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_dispatchCases); ndx++)
678fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	{
679fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski		groupBufferGenerate->addChild(new IndirectDispatchCaseBufferGenerate(testCtx, s_dispatchCases[ndx], glu::GLSL_VERSION_310_ES));
680fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	}
681fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
682fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski	return indirectComputeDispatchTests.release();
683fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski}
684fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski
685fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski} // compute
686fcc71113e2a063a770310435bff4be7984c86f02Maciej Jesionowski} // vkt
687