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