• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 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 Vulkan Fill Buffer Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktApiFillBufferTests.hpp"
26 #include "vktApiBufferAndImageAllocationUtil.hpp"
27 
28 #include "deStringUtil.hpp"
29 #include "deUniquePtr.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestCaseUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuTexture.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuVectorType.hpp"
42 #include "deSharedPtr.hpp"
43 #include <limits>
44 
45 namespace vkt
46 {
47 
48 namespace api
49 {
50 
51 using namespace vk;
52 
53 namespace
54 {
55 
56 struct TestParams
57 {
58 	enum
59 	{
60 		TEST_DATA_SIZE													= 256
61 	};
62 
63 	VkDeviceSize					dstSize;
64 	VkDeviceSize					dstOffset;
65 	VkDeviceSize					size;
66 	deUint32						testData[TEST_DATA_SIZE];
67 	de::SharedPtr<IBufferAllocator>	bufferAllocator;
68 };
69 
70 
71 class FillWholeBufferTestInstance : public vkt::TestInstance
72 {
73 public:
74 							FillWholeBufferTestInstance	(Context& context, const TestParams& testParams);
75 	virtual tcu::TestStatus iterate						(void) override;
76 protected:
77 	// dstSize will be used as the buffer size.
78 	// dstOffset will be used as the offset for vkCmdFillBuffer.
79 	// size in vkCmdFillBuffer will always be VK_WHOLE_SIZE.
80 	const TestParams		m_params;
81 
82 	Move<VkCommandPool>		m_cmdPool;
83 	Move<VkCommandBuffer>	m_cmdBuffer;
84 
85 	Move<VkBuffer>			m_destination;
86 	de::MovePtr<Allocation>	m_destinationBufferAlloc;
87 };
88 
FillWholeBufferTestInstance(Context & context,const TestParams & testParams)89 FillWholeBufferTestInstance::FillWholeBufferTestInstance(Context& context, const TestParams& testParams)
90 	: vkt::TestInstance(context), m_params(testParams)
91 {
92 	const DeviceInterface&	vk					= context.getDeviceInterface();
93 	const VkDevice			vkDevice			= context.getDevice();
94 	const deUint32			queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
95 	Allocator&				memAlloc			= context.getDefaultAllocator();
96 
97 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
98 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
99 	testParams.bufferAllocator->createTestBuffer(m_params.dstSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, context, memAlloc, m_destination, MemoryRequirement::HostVisible, m_destinationBufferAlloc);
100 }
101 
iterate(void)102 tcu::TestStatus FillWholeBufferTestInstance::iterate(void)
103 {
104 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
105 	const VkDevice				vkDevice			= m_context.getDevice();
106 	const VkQueue				queue				= m_context.getUniversalQueue();
107 
108 	// Make sure some stuff below will work.
109 	DE_ASSERT(m_params.dstSize >= sizeof(deUint32));
110 	DE_ASSERT(m_params.dstSize <  static_cast<VkDeviceSize>(std::numeric_limits<size_t>::max()));
111 	DE_ASSERT(m_params.dstOffset < m_params.dstSize);
112 
113 	// Fill buffer from the host and flush buffer memory.
114 	deUint8* bytes = reinterpret_cast<deUint8*>(m_destinationBufferAlloc->getHostPtr());
115 	deMemset(bytes, 0xff, static_cast<size_t>(m_params.dstSize));
116 	flushAlloc(vk, vkDevice, *m_destinationBufferAlloc);
117 
118 	const VkBufferMemoryBarrier	gpuToHostBarrier	=
119 	{
120 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType			sType;
121 		DE_NULL,									// const void*				pNext;
122 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
123 		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags			dstAccessMask;
124 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
125 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
126 		*m_destination,								// VkBuffer					buffer;
127 		0u,											// VkDeviceSize				offset;
128 		VK_WHOLE_SIZE								// VkDeviceSize				size;
129 	};
130 
131 	// Fill buffer using VK_WHOLE_SIZE.
132 	beginCommandBuffer(vk, *m_cmdBuffer);
133 	vk.cmdFillBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, VK_WHOLE_SIZE, deUint32{0x01010101});
134 	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, DE_NULL, 1, &gpuToHostBarrier, 0, DE_NULL);
135 	endCommandBuffer(vk, *m_cmdBuffer);
136 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
137 
138 	// Invalidate buffer memory and check the buffer contains the expected results.
139 	invalidateAlloc(vk, vkDevice, *m_destinationBufferAlloc);
140 
141 	const VkDeviceSize startOfExtra = (m_params.dstSize / sizeof(deUint32)) * sizeof(deUint32);
142 	for (VkDeviceSize i = 0; i < m_params.dstSize; ++i)
143 	{
144 		const deUint8 expectedByte = ((i >= m_params.dstOffset && i < startOfExtra)? 0x01 : 0xff);
145 		if (bytes[i] != expectedByte)
146 		{
147 			std::ostringstream msg;
148 			msg << "Invalid byte at position " << i << " in the buffer (found 0x"
149 				<< std::hex << static_cast<int>(bytes[i]) << " but expected 0x" << static_cast<int>(expectedByte) << ")";
150 			return tcu::TestStatus::fail(msg.str());
151 		}
152 	}
153 
154 	return tcu::TestStatus::pass("Pass");
155 }
156 
157 class FillWholeBufferTestCase : public vkt::TestCase
158 {
159 public:
FillWholeBufferTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams params)160 							FillWholeBufferTestCase	(tcu::TestContext&	testCtx,
161 													 const std::string&	name,
162 													 const std::string&	description,
163 													 const TestParams	params)
164 		: vkt::TestCase(testCtx, name, description), m_params(params)
165 	{}
166 
createInstance(Context & context) const167 	virtual TestInstance*	createInstance			(Context&			context) const override
168 	{
169 		return static_cast<TestInstance*>(new FillWholeBufferTestInstance(context, m_params));
170 	}
171 private:
172 	const TestParams		m_params;
173 };
174 
175 
176 class FillBufferTestInstance : public vkt::TestInstance
177 {
178 public:
179 									FillBufferTestInstance				(Context&					context,
180 																		 TestParams					testParams);
181 	virtual tcu::TestStatus			iterate								(void);
182 protected:
183 	const TestParams				m_params;
184 
185 	Move<VkCommandPool>				m_cmdPool;
186 	Move<VkCommandBuffer>			m_cmdBuffer;
187 	de::MovePtr<tcu::TextureLevel>	m_destinationTextureLevel;
188 	de::MovePtr<tcu::TextureLevel>	m_expectedTextureLevel;
189 
190 	VkCommandBufferBeginInfo		m_cmdBufferBeginInfo;
191 
192 	Move<VkBuffer>					m_destination;
193 	de::MovePtr<Allocation>			m_destinationBufferAlloc;
194 
195 	void							generateBuffer						(tcu::PixelBufferAccess		buffer,
196 																		 int						width,
197 																		 int						height,
198 																		 int						depth = 1);
199 	virtual void					generateExpectedResult				(void);
200 	void							uploadBuffer						(tcu::ConstPixelBufferAccess
201 																									bufferAccess,
202 																		 const Allocation&			bufferAlloc);
203 	virtual tcu::TestStatus			checkTestResult						(tcu::ConstPixelBufferAccess
204 																									result);
calculateSize(tcu::ConstPixelBufferAccess src) const205 	deUint32						calculateSize						(tcu::ConstPixelBufferAccess
206 																									src) const
207 	{
208 		return src.getWidth() * src.getHeight() * src.getDepth() * tcu::getPixelSize(src.getFormat());
209 	}
210 };
211 
FillBufferTestInstance(Context & context,TestParams testParams)212 									FillBufferTestInstance::FillBufferTestInstance
213 																		(Context&					context,
214 																		 TestParams					testParams)
215 									: vkt::TestInstance					(context)
216 									, m_params							(testParams)
217 {
218 	const DeviceInterface&			vk									= context.getDeviceInterface();
219 	const VkDevice					vkDevice							= context.getDevice();
220 	const deUint32					queueFamilyIndex					= context.getUniversalQueueFamilyIndex();
221 	Allocator&						memAlloc							= context.getDefaultAllocator();
222 
223 	// Create command pool
224 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
225 
226 	// Create command buffer
227 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
228 
229 	testParams.bufferAllocator->createTestBuffer(m_params.dstSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, context, memAlloc, m_destination, MemoryRequirement::HostVisible, m_destinationBufferAlloc);
230 }
231 
iterate(void)232 tcu::TestStatus						FillBufferTestInstance::iterate		(void)
233 {
234 	const int						dstLevelWidth						= (int)(m_params.dstSize / 4);
235 	m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), dstLevelWidth, 1));
236 
237 	generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1);
238 
239 	generateExpectedResult();
240 
241 	uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
242 
243 	const DeviceInterface&			vk									= m_context.getDeviceInterface();
244 	const VkDevice					vkDevice							= m_context.getDevice();
245 	const VkQueue					queue								= m_context.getUniversalQueue();
246 
247 	const VkBufferMemoryBarrier		dstBufferBarrier					=
248 	{
249 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,						// VkStructureType			sType;
250 		DE_NULL,														// const void*				pNext;
251 		VK_ACCESS_TRANSFER_WRITE_BIT,									// VkAccessFlags			srcAccessMask;
252 		VK_ACCESS_HOST_READ_BIT,										// VkAccessFlags			dstAccessMask;
253 		VK_QUEUE_FAMILY_IGNORED,										// deUint32					srcQueueFamilyIndex;
254 		VK_QUEUE_FAMILY_IGNORED,										// deUint32					dstQueueFamilyIndex;
255 		*m_destination,													// VkBuffer					buffer;
256 		m_params.dstOffset,												// VkDeviceSize				offset;
257 		VK_WHOLE_SIZE												// VkDeviceSize				size;
258 	};
259 
260 	beginCommandBuffer(vk, *m_cmdBuffer);
261 	vk.cmdFillBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, m_params.size, m_params.testData[0]);
262 	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
263 	endCommandBuffer(vk, *m_cmdBuffer);
264 
265 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
266 
267 	// Read buffer data
268 	de::MovePtr<tcu::TextureLevel>	resultLevel	(new tcu::TextureLevel(m_destinationTextureLevel->getAccess().getFormat(), dstLevelWidth, 1));
269 	invalidateAlloc(vk, vkDevice, *m_destinationBufferAlloc);
270 	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr()));
271 
272 	return checkTestResult(resultLevel->getAccess());
273 }
274 
generateBuffer(tcu::PixelBufferAccess buffer,int width,int height,int depth)275 void								FillBufferTestInstance::generateBuffer
276 																		(tcu::PixelBufferAccess		buffer,
277 																		 int						width,
278 																		 int						height,
279 																		 int						depth)
280 {
281 	for (int z = 0; z < depth; z++)
282 	{
283 		for (int y = 0; y < height; y++)
284 		{
285 			for (int x = 0; x < width; x++)
286 				buffer.setPixel(tcu::UVec4(x, y, z, 255), x, y, z);
287 		}
288 	}
289 }
290 
uploadBuffer(tcu::ConstPixelBufferAccess bufferAccess,const Allocation & bufferAlloc)291 void								FillBufferTestInstance::uploadBuffer
292 																		(tcu::ConstPixelBufferAccess
293 																									bufferAccess,
294 																		 const Allocation&			bufferAlloc)
295 {
296 	const DeviceInterface&			vk									= m_context.getDeviceInterface();
297 	const VkDevice					vkDevice							= m_context.getDevice();
298 	const deUint32					bufferSize							= calculateSize(bufferAccess);
299 
300 	// Write buffer data
301 	deMemcpy(bufferAlloc.getHostPtr(), bufferAccess.getDataPtr(), bufferSize);
302 	flushAlloc(vk, vkDevice, bufferAlloc);
303 }
304 
checkTestResult(tcu::ConstPixelBufferAccess result)305 tcu::TestStatus						FillBufferTestInstance::checkTestResult
306 																		(tcu::ConstPixelBufferAccess
307 																									result)
308 {
309 	const tcu::ConstPixelBufferAccess
310 									expected							= m_expectedTextureLevel->getAccess();
311 	const tcu::UVec4				threshold							(0, 0, 0, 0);
312 
313 	if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparsion", expected, result, threshold, tcu::COMPARE_LOG_RESULT))
314 	{
315 		return tcu::TestStatus::fail("Fill and Update Buffer test");
316 	}
317 
318 	return tcu::TestStatus::pass("Fill and Update Buffer test");
319 }
320 
generateExpectedResult(void)321 void								FillBufferTestInstance::generateExpectedResult
322 																		(void)
323 {
324 	const tcu::ConstPixelBufferAccess
325 									dst									= m_destinationTextureLevel->getAccess();
326 
327 	m_expectedTextureLevel	= de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
328 	tcu::copy(m_expectedTextureLevel->getAccess(), dst);
329 
330 	deUint32*						currentPtr							= (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4;
331 	deUint32*						endPtr								= currentPtr + m_params.size / 4;
332 
333 	while (currentPtr < endPtr)
334 	{
335 		*currentPtr = m_params.testData[0];
336 		currentPtr++;
337 	}
338 }
339 
340 class FillBufferTestCase : public vkt::TestCase
341 {
342 public:
FillBufferTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams params)343 									FillBufferTestCase					(tcu::TestContext&			testCtx,
344 																		 const std::string&			name,
345 																		 const std::string&			description,
346 																		 const TestParams			params)
347 									: vkt::TestCase						(testCtx, name, description)
348 									, m_params							(params)
349 	{}
350 
createInstance(Context & context) const351 	virtual TestInstance*			createInstance						(Context&					context) const
352 	{
353 		return static_cast<TestInstance*>(new FillBufferTestInstance(context, m_params));
354 	}
355 private:
356 	const TestParams				m_params;
357 };
358 
359 // Update Buffer
360 
361 class UpdateBufferTestInstance : public FillBufferTestInstance
362 {
363 public:
UpdateBufferTestInstance(Context & context,TestParams testParams)364 									UpdateBufferTestInstance			(Context&					context,
365 																		 TestParams					testParams)
366 									: FillBufferTestInstance			(context, testParams)
367 	{}
368 	virtual tcu::TestStatus			iterate								(void);
369 
370 protected:
371 	virtual void					generateExpectedResult				(void);
372 };
373 
iterate(void)374 tcu::TestStatus						UpdateBufferTestInstance::iterate	(void)
375 {
376 	const int						dstLevelWidth						= (int)(m_params.dstSize / 4);
377 	m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), dstLevelWidth, 1));
378 
379 	generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1);
380 
381 	generateExpectedResult();
382 
383 	uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
384 
385 	const DeviceInterface&			vk									= m_context.getDeviceInterface();
386 	const VkDevice					vkDevice							= m_context.getDevice();
387 	const VkQueue					queue								= m_context.getUniversalQueue();
388 
389 	const VkBufferMemoryBarrier		dstBufferBarrier					=
390 	{
391 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,						// VkStructureType			sType;
392 		DE_NULL,														// const void*				pNext;
393 		VK_ACCESS_TRANSFER_WRITE_BIT,									// VkAccessFlags			srcAccessMask;
394 		VK_ACCESS_HOST_READ_BIT,										// VkAccessFlags			dstAccessMask;
395 		VK_QUEUE_FAMILY_IGNORED,										// deUint32					srcQueueFamilyIndex;
396 		VK_QUEUE_FAMILY_IGNORED,										// deUint32					dstQueueFamilyIndex;
397 		*m_destination,													// VkBuffer					buffer;
398 		m_params.dstOffset,												// VkDeviceSize				offset;
399 		VK_WHOLE_SIZE												// VkDeviceSize				size;
400 	};
401 
402 	beginCommandBuffer(vk, *m_cmdBuffer);
403 	vk.cmdUpdateBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, m_params.size, m_params.testData);
404 	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
405 	endCommandBuffer(vk, *m_cmdBuffer);
406 
407 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
408 
409 	// Read buffer data
410 	de::MovePtr<tcu::TextureLevel>	resultLevel	(new tcu::TextureLevel(m_destinationTextureLevel->getAccess().getFormat(), dstLevelWidth, 1));
411 	invalidateAlloc(vk, vkDevice, *m_destinationBufferAlloc);
412 	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr()));
413 
414 	return checkTestResult(resultLevel->getAccess());
415 }
416 
generateExpectedResult(void)417 void								UpdateBufferTestInstance::generateExpectedResult
418 																		(void)
419 {
420 	const tcu::ConstPixelBufferAccess
421 									dst									= m_destinationTextureLevel->getAccess();
422 
423 	m_expectedTextureLevel	= de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
424 	tcu::copy(m_expectedTextureLevel->getAccess(), dst);
425 
426 	deUint32*						currentPtr							= (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4;
427 
428 	deMemcpy(currentPtr, m_params.testData, (size_t)m_params.size);
429 }
430 
431 class UpdateBufferTestCase : public vkt::TestCase
432 {
433 public:
UpdateBufferTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams params)434 									UpdateBufferTestCase				(tcu::TestContext&			testCtx,
435 																		 const std::string&			name,
436 																		 const std::string&			description,
437 																		 const TestParams			params)
438 									: vkt::TestCase						(testCtx, name, description)
439 									, m_params							(params)
440 	{}
441 
createInstance(Context & context) const442 	virtual TestInstance*			createInstance						(Context&					context) const
443 	{
444 		return (TestInstance*) new UpdateBufferTestInstance(context, m_params);
445 	}
446 private:
447 	TestParams						m_params;
448 };
449 
450 } // anonymous
451 
createFillAndUpdateBufferTests(tcu::TestContext & testCtx)452 tcu::TestCaseGroup*					createFillAndUpdateBufferTests	(tcu::TestContext&			testCtx)
453 {
454 	const de::SharedPtr<IBufferAllocator>
455 									bufferAllocators[]					=
456 	{
457 		de::SharedPtr<BufferSuballocation>(new BufferSuballocation()),
458 		de::SharedPtr<BufferDedicatedAllocation>(new BufferDedicatedAllocation())
459 	};
460 
461 	de::MovePtr<tcu::TestCaseGroup>	fillAndUpdateBufferTests			(new tcu::TestCaseGroup(testCtx, "fill_and_update_buffer", "Fill and Update Buffer Tests"));
462 	tcu::TestCaseGroup*				bufferViewAllocationGroupTests[]
463 																		=
464 	{
465 		new tcu::TestCaseGroup(testCtx, "suballocation", "BufferView Fill and Update Tests for Suballocated Objects"),
466 		new tcu::TestCaseGroup(testCtx, "dedicated_alloc", "BufferView Fill and Update Tests for Dedicatedly Allocated Objects")
467 	};
468 	for (deUint32 subgroupNdx = 0u; subgroupNdx < DE_LENGTH_OF_ARRAY(bufferViewAllocationGroupTests); ++subgroupNdx)
469 	{
470 		if (bufferViewAllocationGroupTests[subgroupNdx] == DE_NULL)
471 		{
472 			TCU_THROW(InternalError, "Could not create test subgroup.");
473 		}
474 		fillAndUpdateBufferTests->addChild(bufferViewAllocationGroupTests[subgroupNdx]);
475 	}
476 
477 	TestParams						params;
478 
479 	for (deUint32 buffersAllocationNdx = 0u; buffersAllocationNdx < DE_LENGTH_OF_ARRAY(bufferAllocators); ++buffersAllocationNdx)
480 	{
481 		params.dstSize			= TestParams::TEST_DATA_SIZE;
482 		params.bufferAllocator	= bufferAllocators[buffersAllocationNdx];
483 
484 		deUint8* data = (deUint8*) params.testData;
485 		for (deUint32 b = 0u; b < (params.dstSize * sizeof(params.testData[0])); b++)
486 			data[b] = (deUint8) (b % 255);
487 		const deUint32				testCaseGroupNdx					= buffersAllocationNdx;
488 		tcu::TestCaseGroup*			currentTestsGroup					= bufferViewAllocationGroupTests[testCaseGroupNdx];
489 
490 		{
491 			const std::string		description							("whole buffer");
492 			const std::string		testName							("buffer_whole");
493 
494 			params.dstOffset = 0;
495 			params.size = params.dstSize;
496 
497 			currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
498 			currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
499 		}
500 
501 		{
502 			const std::string		description							("first word in buffer");
503 			const std::string		testName							("buffer_first_one");
504 
505 			params.dstOffset = 0;
506 			params.size = 4;
507 
508 			currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
509 			currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
510 		}
511 
512 		{
513 			const std::string		description							("second word in buffer");
514 			const std::string		testName							("buffer_second_one");
515 
516 			params.dstOffset = 4;
517 			params.size = 4;
518 
519 			currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
520 			currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
521 		}
522 
523 		{
524 			const std::string		description							("buffer second part");
525 			const std::string		testName							("buffer_second_part");
526 
527 			params.dstOffset = params.dstSize / 2;
528 			params.size = params.dstSize / 2;
529 
530 			currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
531 			currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
532 		}
533 
534 		// VK_WHOLE_SIZE tests.
535 		{
536 			for (VkDeviceSize i = 0; i < sizeof(deUint32); ++i)
537 			{
538 				for (VkDeviceSize j = 0; j < sizeof(deUint32); ++j)
539 				{
540 					params.dstSize		= TestParams::TEST_DATA_SIZE + i;
541 					params.dstOffset	= j * sizeof(deUint32);
542 					params.size			= VK_WHOLE_SIZE;
543 
544 					const VkDeviceSize	extraBytes	= params.dstSize % sizeof(deUint32);
545 					const std::string	name		= "fill_buffer_vk_whole_size_" + de::toString(extraBytes) + "_extra_bytes_offset_" + de::toString(params.dstOffset);
546 					const std::string	description	= "vkCmdFillBuffer with VK_WHOLE_SIZE, " + de::toString(extraBytes) + " extra bytes and offset " + de::toString(params.dstOffset);
547 
548 					currentTestsGroup->addChild(new FillWholeBufferTestCase{testCtx, name, description, params});
549 				}
550 			}
551 		}
552 	}
553 
554 	return fillAndUpdateBufferTests.release();
555 }
556 
557 } // api
558 } // vkt
559