• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Protected memory copy image to buffer tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemCopyImageToBufferTests.hpp"
26 
27 #include "deRandom.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuVector.hpp"
30 #include "tcuVectorUtil.hpp"
31 
32 #include "vkPrograms.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestGroupUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 
39 #include "vktProtectedMemContext.hpp"
40 #include "vktProtectedMemUtils.hpp"
41 #include "vktProtectedMemBufferValidator.hpp"
42 
43 namespace vkt
44 {
45 namespace ProtectedMem
46 {
47 
48 namespace
49 {
50 
51 enum {
52 	BUFFER_SIZE		= 256,
53 	RENDER_WIDTH	= 8,
54 	RENDER_HEIGHT	= 8,
55 
56 	MAX_POSITION	= BUFFER_SIZE / 4,
57 };
58 
59 template<typename T>
60 class CopyImageToBufferTestInstance : public ProtectedTestInstance
61 {
62 public:
63 									CopyImageToBufferTestInstance	(Context&							ctx,
64 																	 const vk::VkClearColorValue		fillValue,
65 																	 const BufferValidator<T>&			validator,
66 																	 const CmdBufferType				cmdBufferType,
67 																	 const std::vector<std::string>&	extensions);
68 	virtual tcu::TestStatus			iterate							(void);
69 
70 private:
71 	const vk::VkFormat				m_imageFormat;
72 	const vk::VkClearColorValue		m_fillValue;
73 	const BufferValidator<T>&		m_validator;
74 	const CmdBufferType					m_cmdBufferType;
75 };
76 
77 
78 template<typename T>
79 class CopyImageToBufferTestCase : public TestCase
80 {
81 public:
CopyImageToBufferTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearColorValue fillValue,ValidationData<T> data,CmdBufferType cmdBufferType,vk::VkFormat format,bool pipelineProtectedAccess)82 							CopyImageToBufferTestCase	(tcu::TestContext&		testCtx,
83 														 const std::string&		name,
84 														 vk::VkClearColorValue	fillValue,
85 														 ValidationData<T>		data,
86 														 CmdBufferType			cmdBufferType,
87 														 vk::VkFormat			format,
88 														 bool					pipelineProtectedAccess)
89 								: TestCase					(testCtx, name, "Copy image to buffer.")
90 								, m_fillValue				(fillValue)
91 								, m_validator				(data, format)
92 								, m_cmdBufferType			(cmdBufferType)
93 								, m_pipelineProtectedAccess	(pipelineProtectedAccess)
94 							{
95 							}
96 
~CopyImageToBufferTestCase(void)97 	virtual					~CopyImageToBufferTestCase	(void) {}
createInstance(Context & ctx) const98 	virtual TestInstance*	createInstance				(Context& ctx) const
99 							{
100 								std::vector<std::string> extensions;
101 								if (m_pipelineProtectedAccess) {
102 									extensions.push_back("VK_EXT_pipeline_protected_access");
103 								}
104 								return new CopyImageToBufferTestInstance<T>(ctx, m_fillValue, m_validator, m_cmdBufferType, extensions);
105 							}
initPrograms(vk::SourceCollections & programCollection) const106 	virtual void			initPrograms				(vk::SourceCollections&	programCollection) const
107 							{
108 								m_validator.initPrograms(programCollection);
109 							}
checkSupport(Context & context) const110 	virtual void			checkSupport				(Context& context) const
111 							{
112 								checkProtectedQueueSupport(context);
113 #ifdef CTS_USES_VULKANSC
114 								if (m_cmdBufferType == CMD_BUFFER_SECONDARY && context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
115 									TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
116 #endif // CTS_USES_VULKANSC
117 							}
118 private:
119 	vk::VkClearColorValue	m_fillValue;
120 	BufferValidator<T>		m_validator;
121 	CmdBufferType			m_cmdBufferType;
122 	bool					m_pipelineProtectedAccess;
123 };
124 
125 template<typename T>
CopyImageToBufferTestInstance(Context & ctx,const vk::VkClearColorValue fillValue,const BufferValidator<T> & validator,const CmdBufferType cmdBufferType,const std::vector<std::string> & extensions)126 CopyImageToBufferTestInstance<T>::CopyImageToBufferTestInstance	(Context&						ctx,
127 																 const vk::VkClearColorValue	fillValue,
128 																 const BufferValidator<T>&		validator,
129 																 const CmdBufferType			cmdBufferType,
130 																 const std::vector<std::string>& extensions)
131 	: ProtectedTestInstance	(ctx, extensions)
132 	, m_imageFormat			(vk::VK_FORMAT_R32G32B32A32_UINT)
133 	, m_fillValue			(fillValue)
134 	, m_validator			(validator)
135 	, m_cmdBufferType		(cmdBufferType)
136 {
137 }
138 
139 template<typename T>
iterate()140 tcu::TestStatus CopyImageToBufferTestInstance<T>::iterate()
141 {
142 	ProtectedContext&					ctx					(m_protectedContext);
143 	const vk::DeviceInterface&			vk					= ctx.getDeviceInterface();
144 	const vk::VkDevice					device				= ctx.getDevice();
145 	const vk::VkQueue					queue				= ctx.getQueue();
146 	const deUint32						queueFamilyIndex	= ctx.getQueueFamilyIndex();
147 
148 	// Create image
149 	de::MovePtr<vk::ImageWithMemory>	colorImage			= createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
150 																			RENDER_WIDTH, RENDER_HEIGHT,
151 																			m_imageFormat,
152 																			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT
153 																			| vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
154 	de::MovePtr<vk::BufferWithMemory>	dstBuffer			(makeBuffer(ctx,
155 																		PROTECTION_ENABLED,
156 																		queueFamilyIndex,
157 																		(deUint32)(BUFFER_SIZE * sizeof(deUint32)),
158 																		vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
159 																			| vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
160 																		vk::MemoryRequirement::Protected));
161 
162 	vk::Unique<vk::VkCommandPool>		cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
163 	vk::Unique<vk::VkCommandBuffer>		cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
164 	vk::Unique<vk::VkCommandBuffer>		secondaryCmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
165 	vk::VkCommandBuffer					targetCmdBuffer		= (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
166 
167 	// Begin cmd buffer
168 	beginCommandBuffer(vk, *cmdBuffer);
169 
170 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
171 	{
172 		// Begin secondary command buffer
173 		const vk::VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
174 		{
175 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
176 			DE_NULL,
177 			(vk::VkRenderPass)0u,										// renderPass
178 			0u,															// subpass
179 			(vk::VkFramebuffer)0u,										// framebuffer
180 			VK_FALSE,													// occlusionQueryEnable
181 			(vk::VkQueryControlFlags)0u,								// queryFlags
182 			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
183 		};
184 		beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, secCmdBufInheritInfo);
185 	}
186 
187 	// Start image barrier for source image.
188 	{
189 		const vk::VkImageMemoryBarrier	startImgBarrier		=
190 		{
191 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
192 			DE_NULL,											// const void*			pNext
193 			0,													// VkAccessFlags		srcAccessMask
194 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		dstAccessMask
195 			vk::VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout		oldLayout
196 			vk::VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout		newLayout
197 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
198 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
199 			**colorImage,										// VkImage				image
200 			{
201 				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags	aspectMask
202 				0u,												// uint32_t				baseMipLevel
203 				1u,												// uint32_t				mipLevels
204 				0u,												// uint32_t				baseArraySlice
205 				1u,												// uint32_t				subresourceRange
206 			}
207 		};
208 
209 		vk.cmdPipelineBarrier(targetCmdBuffer,
210 							  vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
211 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
212 							  (vk::VkDependencyFlags)0,
213 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
214 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
215 							  1, &startImgBarrier);
216 	}
217 
218 	// Image clear
219 	const vk::VkImageSubresourceRange subresourceRange =
220 	{
221 		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
222 		0u,								// uint32_t				baseMipLevel
223 		1u,								// uint32_t				levelCount
224 		0u,								// uint32_t				baseArrayLayer
225 		1u,								// uint32_t				layerCount
226 	};
227 
228 	vk.cmdClearColorImage(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_GENERAL, &m_fillValue, 1, &subresourceRange);
229 
230 	// Image barrier to change accessMask to transfer read bit for source image.
231 	{
232 		const vk::VkImageMemoryBarrier initializeBarrier =
233 		{
234 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
235 			DE_NULL,											// const void*			pNext
236 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		srcAccessMask
237 			vk::VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags		dstAccessMask
238 			vk::VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout		oldLayout
239 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout		newLayout
240 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
241 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
242 			**colorImage,										// VkImage				image
243 			{
244 				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags	aspectMask
245 				0u,												// uint32_t				baseMipLevel
246 				1u,												// uint32_t				mipLevels
247 				0u,												// uint32_t				baseArraySlice
248 				1u,												// uint32_t				subresourceRange
249 			}
250 		};
251 
252 		vk.cmdPipelineBarrier(targetCmdBuffer,
253 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
254 							  vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
255 							  (vk::VkDependencyFlags)0,
256 							  0, (const vk::VkMemoryBarrier*)DE_NULL,
257 							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
258 							  1, &initializeBarrier);
259 	}
260 
261 	// Copy image to buffer
262 	const vk::VkImageSubresourceLayers	subresourceLayers	=
263 	{
264 		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
265 		0u,								// uint32_t				mipLevel
266 		0u,								// uint32_t				baseArrayLayer
267 		1u,								// uint32_t				layerCount
268 	};
269 	const vk::VkOffset3D				nullOffset			= {0u, 0u, 0u};
270 	const vk::VkExtent3D				imageExtent			= {(deUint32)RENDER_WIDTH, (deUint32)RENDER_HEIGHT, 1u};
271 	const vk::VkBufferImageCopy			copyRegion			=
272 	{
273 		0ull,							// VkDeviceSize				srcOffset;
274 		0,								// uint32_t					bufferRowLength
275 		0,								// uint32_t					bufferImageHeight
276 		subresourceLayers,				// VkImageSubresourceLayers	imageSubresource
277 		nullOffset,						// VkOffset3D				imageOffset
278 		imageExtent,					// VkExtent3D				imageExtent
279 	};
280 	vk.cmdCopyImageToBuffer(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **dstBuffer, 1u, &copyRegion);
281 
282 	{
283 		// Buffer validator reads buffer in compute shader
284 		const vk::VkBufferMemoryBarrier	endBufferBarrier		=
285 		{
286 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType		sType
287 			DE_NULL,											// const void*			pNext
288 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		srcAccessMask
289 			vk::VK_ACCESS_SHADER_READ_BIT,						// VkAccessFlags		dstAccessMask
290 			queueFamilyIndex,									// uint32_t				srcQueueFamilyIndex
291 			queueFamilyIndex,									// uint32_t				dstQueueFamilyIndex
292 			**dstBuffer,										// VkBuffer				buffer
293 			0u,													// VkDeviceSize			offset
294 			VK_WHOLE_SIZE,										// VkDeviceSize			size
295 		};
296 		vk.cmdPipelineBarrier(targetCmdBuffer,
297 								vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
298 								vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
299 								(vk::VkDependencyFlags)0,
300 								0, (const vk::VkMemoryBarrier*)DE_NULL,
301 								1, &endBufferBarrier,
302 								0, (const vk::VkImageMemoryBarrier*)DE_NULL);
303 	}
304 
305 	if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
306 	{
307 		endCommandBuffer(vk, *secondaryCmdBuffer);
308 		vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
309 	}
310 
311 	endCommandBuffer(vk, *cmdBuffer);
312 
313 	// Submit command buffer
314 	const vk::Unique<vk::VkFence>	fence		(vk::createFence(vk, device));
315 	VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
316 
317 	// Log out test data
318 	ctx.getTestContext().getLog()
319 		<< tcu::TestLog::Message << "Fill value: " << m_fillValue << tcu::TestLog::EndMessage;
320 
321 	// Validate resulting buffer
322 	if (m_validator.validateBuffer(ctx, **dstBuffer))
323 		return tcu::TestStatus::pass("Everything went OK");
324 	else
325 		return tcu::TestStatus::fail("Something went really wrong");
326 }
327 
createCopyImageToFloatBufferTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)328 tcu::TestCaseGroup*	createCopyImageToFloatBufferTests(tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
329 {
330 	struct {
331 		const vk::VkClearColorValue		fillValue;
332 		const ValidationDataVec4		data;
333 	} testData[] = {
334 		{	{ { 0.0f, 0.0f, 0.0f, 0.0f } },
335 			{
336 				{ tcu::IVec4(0),	tcu::IVec4(1),		tcu::IVec4(3),		tcu::IVec4(7)		},
337 				{ tcu::Vec4(0.0f),	tcu::Vec4(0.0f),	tcu::Vec4(0.0f),	tcu::Vec4(0.0f)		}
338 			}
339 		},
340 		{	{ { 1.0f, 1.0f, 1.0f, 1.0f } },
341 			{
342 				{ tcu::IVec4(2),	tcu::IVec4(4),		tcu::IVec4(16),		tcu::IVec4(15)		},
343 				{ tcu::Vec4(1.0f),	tcu::Vec4(1.0f),	tcu::Vec4(1.0f),	tcu::Vec4(1.0f)		}
344 			}
345 		},
346 		{	{ { 0.24f, 0.24f, 0.24f, 0.24f } },
347 			{
348 				{ tcu::IVec4(3),	tcu::IVec4(7),		tcu::IVec4(17),		tcu::IVec4(37)		},
349 				{ tcu::Vec4(0.24f),	tcu::Vec4(0.24f),	tcu::Vec4(0.24f),	tcu::Vec4(0.24f)	}
350 			}
351 		},
352 		{	{ { 0.68f, 0.68f, 0.68f, 0.68f } },
353 			{
354 				{ tcu::IVec4(7),	tcu::IVec4(11),		tcu::IVec4(21),		tcu::IVec4(40)		},
355 				{ tcu::Vec4(0.68f),	tcu::Vec4(0.68f),	tcu::Vec4(0.68f),	tcu::Vec4(0.68f)	}
356 			}
357 		},
358 		{	{ { 0.92f, 0.92f, 0.92f, 0.92f } },
359 			{
360 				{ tcu::IVec4(5),	tcu::IVec4(21),		tcu::IVec4(40),		tcu::IVec4(57)		},
361 				{ tcu::Vec4(0.92f),	tcu::Vec4(0.92f),	tcu::Vec4(0.92f),	tcu::Vec4(0.92f)	}
362 			}
363 		},
364 		{	{ { 0.49f, 0.49f, 0.49f, 0.49f } },
365 			{
366 				{ tcu::IVec4(23),	tcu::IVec4(37),		tcu::IVec4(51),		tcu::IVec4(63)		},
367 				{ tcu::Vec4(0.49f),	tcu::Vec4(0.49f),	tcu::Vec4(0.49f),	tcu::Vec4(0.49f)	}
368 			}
369 		},
370 	};
371 
372 	bool pipelineProtectedAccess[] = {
373 		false,
374 #ifndef CTS_USES_VULKANSC
375 		true,
376 #endif
377 	};
378 
379 	de::MovePtr<tcu::TestCaseGroup>	copyStaticTests		(new tcu::TestCaseGroup(testCtx, "static", "Copy Image to Buffer Tests with static input"));
380 
381 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
382 	{
383 		for (int ppa = 0; ppa < DE_LENGTH_OF_ARRAY(pipelineProtectedAccess); ++ppa) {
384 			DE_ASSERT(testData[ndx].data.positions[0].x() < MAX_POSITION);
385 			DE_ASSERT(testData[ndx].data.positions[1].x() < MAX_POSITION);
386 			DE_ASSERT(testData[ndx].data.positions[2].x() < MAX_POSITION);
387 			DE_ASSERT(testData[ndx].data.positions[3].x() < MAX_POSITION);
388 
389 			const std::string name = "copy_" + de::toString(ndx + 1) + (pipelineProtectedAccess[ppa] ? "_protected_access" : "");;
390 			copyStaticTests->addChild(new CopyImageToBufferTestCase<tcu::Vec4>(testCtx, name.c_str(), testData[ndx].fillValue, testData[ndx].data, cmdBufferType, vk::VK_FORMAT_R32G32B32A32_SFLOAT, pipelineProtectedAccess[ppa]));
391 		}
392 	}
393 
394 	/* Add a few randomized tests */
395 	de::MovePtr<tcu::TestCaseGroup>	copyRandomTests		(new tcu::TestCaseGroup(testCtx, "random", "Copy Image to Buffer Tests with random input"));
396 	const int						testCount			= 10;
397 	de::Random						rnd					(testCtx.getCommandLine().getBaseSeed());
398 	for (int ndx = 0; ndx < testCount; ++ndx)
399 	{
400 		for (int ppa = 0; ppa < DE_LENGTH_OF_ARRAY(pipelineProtectedAccess); ++ppa) {
401 			const std::string	name = "copy_" + de::toString(ndx + 1) + (pipelineProtectedAccess[ppa] ? "_protected_access" : "");
402 			vk::VkClearValue	clearValue = vk::makeClearValueColorVec4(tcu::randomVec4(rnd));
403 			const tcu::Vec4		refValue(clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]);
404 			const tcu::IVec4	vec0 = tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
405 			const tcu::IVec4	vec1 = tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
406 			const tcu::IVec4	vec2 = tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
407 			const tcu::IVec4	vec3 = tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
408 
409 			ValidationDataVec4	data =
410 			{
411 				{ vec0, vec1, vec2, vec3 },
412 				{ refValue, refValue, refValue, refValue }
413 			};
414 
415 			DE_ASSERT(data.positions[0].x() < MAX_POSITION);
416 			DE_ASSERT(data.positions[1].x() < MAX_POSITION);
417 			DE_ASSERT(data.positions[2].x() < MAX_POSITION);
418 			DE_ASSERT(data.positions[3].x() < MAX_POSITION);
419 
420 			copyRandomTests->addChild(new CopyImageToBufferTestCase<tcu::Vec4>(testCtx, name.c_str(), clearValue.color, data, cmdBufferType, vk::VK_FORMAT_R32G32B32A32_SFLOAT, pipelineProtectedAccess[ppa]));
421 		}
422 	}
423 
424 	std::string groupName = getCmdBufferTypeStr(cmdBufferType);
425 	std::string groupDesc = "Copy Image to Buffer Tests with " + groupName + " command buffer";
426 	de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
427 	copyTests->addChild(copyStaticTests.release());
428 	copyTests->addChild(copyRandomTests.release());
429 	return copyTests.release();
430 }
431 
432 } // anonymous
433 
createCopyImageToFloatBufferTests(tcu::TestContext & testCtx)434 tcu::TestCaseGroup*	createCopyImageToFloatBufferTests (tcu::TestContext& testCtx)
435 {
436 	de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, "copy_image_to_float_buffer", "Copy Image to Buffer Tests"));
437 
438 	copyTests->addChild(createCopyImageToFloatBufferTests(testCtx, CMD_BUFFER_PRIMARY));
439 	copyTests->addChild(createCopyImageToFloatBufferTests(testCtx, CMD_BUFFER_SECONDARY));
440 
441 	return copyTests.release();
442 }
443 
444 } // ProtectedMem
445 } // vkt
446