1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 The Android Open Source Project
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 Image size Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktImageSizeTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageTexture.hpp"
29 
30 #include "vkDefs.hpp"
31 #include "vkRef.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 
41 #include "deUniquePtr.hpp"
42 #include "deStringUtil.hpp"
43 
44 #include <string>
45 
46 using namespace vk;
47 
48 namespace vkt
49 {
50 namespace image
51 {
52 namespace
53 {
54 
55 //! Get a texture based on image type and suggested size.
getTexture(const ImageType imageType,const tcu::IVec3 & size)56 Texture getTexture (const ImageType imageType, const tcu::IVec3& size)
57 {
58 	switch (imageType)
59 	{
60 		case IMAGE_TYPE_1D:
61 		case IMAGE_TYPE_BUFFER:
62 			return Texture(imageType, tcu::IVec3(size.x(), 1, 1), 1);
63 
64 		case IMAGE_TYPE_1D_ARRAY:
65 			return Texture(imageType, tcu::IVec3(size.x(), 1, 1), size.y());
66 
67 		case IMAGE_TYPE_2D:
68 			return Texture(imageType, tcu::IVec3(size.x(), size.y(), 1), 1);
69 
70 		case IMAGE_TYPE_2D_ARRAY:
71 			return Texture(imageType, tcu::IVec3(size.x(), size.y(), 1), size.z());
72 
73 		case IMAGE_TYPE_CUBE:
74 			return Texture(imageType, tcu::IVec3(size.x(), size.x(), 1), 6);
75 
76 		case IMAGE_TYPE_CUBE_ARRAY:
77 			return Texture(imageType, tcu::IVec3(size.x(), size.x(), 1), 2*6);
78 
79 		case IMAGE_TYPE_3D:
80 			return Texture(imageType, size, 1);
81 
82 		default:
83 			DE_FATAL("Internal error");
84 			return Texture(IMAGE_TYPE_LAST, tcu::IVec3(), 0);
85 	}
86 }
87 
makeImageCreateInfo(const Texture & texture,const VkFormat format)88 inline VkImageCreateInfo makeImageCreateInfo (const Texture& texture, const VkFormat format)
89 {
90 	const VkImageCreateInfo imageParams =
91 	{
92 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,												// VkStructureType			sType;
93 		DE_NULL,																			// const void*				pNext;
94 		(isCube(texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u),	// VkImageCreateFlags		flags;
95 		mapImageType(texture.type()),														// VkImageType				imageType;
96 		format,																				// VkFormat					format;
97 		makeExtent3D(texture.layerSize()),													// VkExtent3D				extent;
98 		1u,																					// deUint32					mipLevels;
99 		(deUint32)texture.numLayers(),														// deUint32					arrayLayers;
100 		VK_SAMPLE_COUNT_1_BIT,																// VkSampleCountFlagBits	samples;
101 		VK_IMAGE_TILING_OPTIMAL,															// VkImageTiling			tiling;
102 		VK_IMAGE_USAGE_STORAGE_BIT,															// VkImageUsageFlags		usage;
103 		VK_SHARING_MODE_EXCLUSIVE,															// VkSharingMode			sharingMode;
104 		0u,																					// deUint32					queueFamilyIndexCount;
105 		DE_NULL,																			// const deUint32*			pQueueFamilyIndices;
106 		VK_IMAGE_LAYOUT_UNDEFINED,															// VkImageLayout			initialLayout;
107 	};
108 	return imageParams;
109 }
110 
111 //! Interpret the memory as IVec3
readIVec3(const void * const data)112 inline tcu::IVec3 readIVec3 (const void* const data)
113 {
114 	const int* const p = reinterpret_cast<const int*>(data);
115 	return tcu::IVec3(p[0], p[1], p[2]);
116 }
117 
getExpectedImageSizeResult(const Texture & texture)118 tcu::IVec3 getExpectedImageSizeResult (const Texture& texture)
119 {
120 	// GLSL imageSize() function returns:
121 	// z = 0 for cubes
122 	// z = N for cube arrays, where N is the number of cubes
123 	// y or z = L where L is the number of layers for other array types (e.g. 1D array, 2D array)
124 	// z = D where D is the depth of 3d image
125 
126 	const tcu::IVec3 size = texture.size();
127 	const int numCubeFaces = 6;
128 
129 	switch (texture.type())
130 	{
131 		case IMAGE_TYPE_1D:
132 		case IMAGE_TYPE_BUFFER:
133 			return tcu::IVec3(size.x(), 0, 0);
134 
135 		case IMAGE_TYPE_1D_ARRAY:
136 		case IMAGE_TYPE_2D:
137 		case IMAGE_TYPE_CUBE:
138 			return tcu::IVec3(size.x(), size.y(), 0);
139 
140 		case IMAGE_TYPE_2D_ARRAY:
141 		case IMAGE_TYPE_3D:
142 			return size;
143 
144 		case IMAGE_TYPE_CUBE_ARRAY:
145 			return tcu::IVec3(size.x(), size.y(), size.z() / numCubeFaces);
146 
147 		default:
148 			DE_FATAL("Internal error");
149 			return tcu::IVec3();
150 	}
151 }
152 
153 class SizeTest : public TestCase
154 {
155 public:
156 	enum TestFlags
157 	{
158 		FLAG_READONLY_IMAGE		= 1u << 0,
159 		FLAG_WRITEONLY_IMAGE	= 1u << 1,
160 	};
161 
162 						SizeTest			(tcu::TestContext&	testCtx,
163 											 const std::string&	name,
164 											 const std::string&	description,
165 											 const Texture&		texture,
166 											 const VkFormat		format,
167 											 const deUint32		flags = 0);
168 
169 	void				initPrograms		(SourceCollections& programCollection) const;
170 	TestInstance*		createInstance		(Context&			context) const;
171 
172 private:
173 	const Texture		m_texture;
174 	const VkFormat		m_format;
175 	const bool			m_useReadonly;
176 	const bool			m_useWriteonly;
177 };
178 
SizeTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const Texture & texture,const VkFormat format,const deUint32 flags)179 SizeTest::SizeTest (tcu::TestContext&		testCtx,
180 					const std::string&		name,
181 					const std::string&		description,
182 					const Texture&			texture,
183 					const VkFormat			format,
184 					const deUint32			flags)
185 	: TestCase			(testCtx, name, description)
186 	, m_texture			(texture)
187 	, m_format			(format)
188 	, m_useReadonly		((flags & FLAG_READONLY_IMAGE) != 0)
189 	, m_useWriteonly	((flags & FLAG_WRITEONLY_IMAGE) != 0)
190 {
191 	// We expect at least one flag to be set.
192 	DE_ASSERT(m_useReadonly || m_useWriteonly);
193 }
194 
initPrograms(SourceCollections & programCollection) const195 void SizeTest::initPrograms (SourceCollections& programCollection) const
196 {
197 	const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
198 	const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), m_texture.type());
199 	const int dimension = m_texture.dimension();
200 
201 	std::ostringstream accessQualifier;
202 	if (m_useReadonly)
203 		accessQualifier << " readonly";
204 	if (m_useWriteonly)
205 		accessQualifier << " writeonly";
206 
207 	std::ostringstream src;
208 	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
209 		<< "\n"
210 		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
211 		<< "layout (binding = 0, " << formatQualifierStr << ")" << accessQualifier.str() << " uniform highp " << imageTypeStr << " u_image;\n"
212 		<< "layout (binding = 1) writeonly buffer Output {\n"
213 		<< "    ivec3 size;\n"
214 		<< "} sb_out;\n"
215 		<< "\n"
216 		<< "void main (void)\n"
217 		<< "{\n"
218 		<< (dimension == 1 ?
219 			"    sb_out.size = ivec3(imageSize(u_image), 0, 0);\n"
220 			: dimension == 2 || m_texture.type() == IMAGE_TYPE_CUBE ?		// cubes return ivec2
221 			"    sb_out.size = ivec3(imageSize(u_image), 0);\n"
222 			: dimension == 3 ?												// cube arrays return ivec3
223 			"    sb_out.size = imageSize(u_image);\n"
224 			: "")
225 		<< "}\n";
226 
227 	programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
228 }
229 
230 //! Build a case name, e.g. "readonly_writeonly_32x32"
getCaseName(const Texture & texture,const deUint32 flags)231 std::string getCaseName (const Texture& texture, const deUint32 flags)
232 {
233 	std::ostringstream str;
234 	str << ((flags & SizeTest::FLAG_READONLY_IMAGE) != 0 ? "readonly_" : "")
235 		<< ((flags & SizeTest::FLAG_WRITEONLY_IMAGE) != 0 ? "writeonly_" : "");
236 
237 	const int numComponents = texture.dimension();
238 	for (int i = 0; i < numComponents; ++i)
239 		str << (i == 0 ? "" : "x") << texture.size()[i];
240 
241 	return str.str();
242 }
243 
244 //! Base test instance for image and buffer tests
245 class SizeTestInstance : public TestInstance
246 {
247 public:
248 									SizeTestInstance			(Context&				context,
249 																 const Texture&			texture,
250 																 const VkFormat			format);
251 
252 	tcu::TestStatus                 iterate						(void);
253 	void							checkRequirements			(void) const;
254 
~SizeTestInstance(void)255 	virtual							~SizeTestInstance			(void) {}
256 
257 protected:
258 	virtual VkDescriptorSetLayout	prepareDescriptors			(void) = 0;
259 	virtual VkDescriptorSet         getDescriptorSet			(void) const = 0;
260 	virtual void					commandBeforeCompute		(const VkCommandBuffer	cmdBuffer) = 0;
261 
262 	const Texture					m_texture;
263 	const VkFormat					m_format;
264 	const VkDeviceSize				m_resultBufferSizeBytes;
265 	de::MovePtr<Buffer>				m_resultBuffer;				//!< Shader writes the output here.
266 };
267 
SizeTestInstance(Context & context,const Texture & texture,const VkFormat format)268 SizeTestInstance::SizeTestInstance (Context& context, const Texture& texture, const VkFormat format)
269 	: TestInstance				(context)
270 	, m_texture					(texture)
271 	, m_format					(format)
272 	, m_resultBufferSizeBytes	(3 * sizeof(deUint32))	// ivec3 in shader
273 {
274 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
275 	const VkDevice			device		= m_context.getDevice();
276 	Allocator&				allocator	= m_context.getDefaultAllocator();
277 
278 	// Create an SSBO for shader output.
279 
280 	m_resultBuffer = de::MovePtr<Buffer>(new Buffer(
281 		vk, device, allocator,
282 		makeBufferCreateInfo(m_resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
283 		MemoryRequirement::HostVisible));
284 }
285 
checkRequirements(void) const286 void SizeTestInstance::checkRequirements (void) const
287 {
288 	if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY && !m_context.getDeviceFeatures().imageCubeArray)
289 	{
290 		TCU_THROW(NotSupportedError, "imageCubeArray feature not supported");
291 	}
292 }
293 
iterate(void)294 tcu::TestStatus SizeTestInstance::iterate (void)
295 {
296 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
297 	const VkDevice			device				= m_context.getDevice();
298 	const VkQueue			queue				= m_context.getUniversalQueue();
299 	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
300 
301 	checkRequirements();
302 
303 	// Create memory barriers.
304 
305 	const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
306 		VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
307 		m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
308 
309 	// Create the pipeline.
310 
311 	const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
312 
313 	const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
314 	const VkDescriptorSet descriptorSet = getDescriptorSet();
315 
316 	const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
317 	const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
318 
319 	const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
320 	const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
321 
322 	beginCommandBuffer(vk, *cmdBuffer);
323 
324 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
325 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
326 
327 	commandBeforeCompute(*cmdBuffer);
328 	vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
329 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
330 
331 	endCommandBuffer(vk, *cmdBuffer);
332 
333 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
334 
335 	// Compare the result.
336 
337 	const Allocation& bufferAlloc = m_resultBuffer->getAllocation();
338 	invalidateAlloc(vk, device, bufferAlloc);
339 
340 	const tcu::IVec3 resultSize = readIVec3(bufferAlloc.getHostPtr());
341 	const tcu::IVec3 expectedSize = getExpectedImageSizeResult(m_texture);
342 
343 	if (resultSize != expectedSize)
344 		return tcu::TestStatus::fail("Incorrect imageSize(): expected " + de::toString(expectedSize) + " but got " + de::toString(resultSize));
345 	else
346 		return tcu::TestStatus::pass("Passed");
347 }
348 
349 class ImageSizeTestInstance : public SizeTestInstance
350 {
351 public:
352 									ImageSizeTestInstance		(Context&				context,
353 																 const Texture&			texture,
354 																 const VkFormat			format);
355 
356 protected:
357 	VkDescriptorSetLayout			prepareDescriptors			(void);
358 	void							commandBeforeCompute		(const VkCommandBuffer	cmdBuffer);
359 
getDescriptorSet(void) const360 	VkDescriptorSet                 getDescriptorSet			(void) const { return *m_descriptorSet; }
361 
362 	de::MovePtr<Image>				m_image;
363 	Move<VkImageView>				m_imageView;
364 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
365 	Move<VkDescriptorPool>			m_descriptorPool;
366 	Move<VkDescriptorSet>			m_descriptorSet;
367 };
368 
ImageSizeTestInstance(Context & context,const Texture & texture,const VkFormat format)369 ImageSizeTestInstance::ImageSizeTestInstance (Context& context, const Texture& texture, const VkFormat format)
370 	: SizeTestInstance	(context, texture, format)
371 {
372 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
373 	const VkDevice			device		= m_context.getDevice();
374 	Allocator&				allocator	= m_context.getDefaultAllocator();
375 
376 	// Create an image. Its data be uninitialized, as we're not reading from it.
377 
378 	m_image = de::MovePtr<Image>(new Image(vk, device, allocator, makeImageCreateInfo(m_texture, m_format), MemoryRequirement::Any));
379 
380 	const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
381 	m_imageView = makeImageView(vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format, subresourceRange);
382 }
383 
prepareDescriptors(void)384 VkDescriptorSetLayout ImageSizeTestInstance::prepareDescriptors (void)
385 {
386 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
387 	const VkDevice			device	= m_context.getDevice();
388 
389 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
390 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
391 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
392 		.build(vk, device);
393 
394 	m_descriptorPool = DescriptorPoolBuilder()
395 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
396 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
397 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
398 
399 	m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
400 
401 	const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
402 	const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
403 
404 	DescriptorSetUpdateBuilder()
405 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
406 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
407 		.update(vk, device);
408 
409 	return *m_descriptorSetLayout;
410 }
411 
commandBeforeCompute(const VkCommandBuffer cmdBuffer)412 void ImageSizeTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
413 {
414 	const DeviceInterface& vk = m_context.getDeviceInterface();
415 
416 	const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
417 	const VkImageMemoryBarrier barrierSetImageLayout = makeImageMemoryBarrier(
418 		0u, 0u,
419 		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
420 		m_image->get(), subresourceRange);
421 
422 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierSetImageLayout);
423 }
424 
425 class BufferSizeTestInstance : public SizeTestInstance
426 {
427 public:
428 									BufferSizeTestInstance		(Context&				context,
429 																 const Texture&			texture,
430 																 const VkFormat			format);
431 
432 protected:
433 	VkDescriptorSetLayout			prepareDescriptors			(void);
434 
commandBeforeCompute(const VkCommandBuffer)435 	void							commandBeforeCompute		(const VkCommandBuffer) {}
getDescriptorSet(void) const436 	VkDescriptorSet					getDescriptorSet			(void) const { return *m_descriptorSet; }
437 
438 	de::MovePtr<Buffer>				m_imageBuffer;
439 	Move<VkBufferView>				m_bufferView;
440 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
441 	Move<VkDescriptorPool>			m_descriptorPool;
442 	Move<VkDescriptorSet>			m_descriptorSet;
443 };
444 
BufferSizeTestInstance(Context & context,const Texture & texture,const VkFormat format)445 BufferSizeTestInstance::BufferSizeTestInstance (Context& context, const Texture& texture, const VkFormat format)
446 	: SizeTestInstance	(context, texture, format)
447 {
448 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
449 	const VkDevice			device		= m_context.getDevice();
450 	Allocator&				allocator	= m_context.getDefaultAllocator();
451 
452 	// Create a texel storage buffer. Its data be uninitialized, as we're not reading from it.
453 
454 	const VkDeviceSize imageSizeBytes = getImageSizeBytes(m_texture.size(), m_format);
455 	m_imageBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
456 		makeBufferCreateInfo(imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), MemoryRequirement::Any));
457 
458 	m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, imageSizeBytes);
459 }
460 
prepareDescriptors(void)461 VkDescriptorSetLayout BufferSizeTestInstance::prepareDescriptors (void)
462 {
463 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
464 	const VkDevice			device	= m_context.getDevice();
465 
466 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
467 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
468 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
469 		.build(vk, device);
470 
471 	m_descriptorPool = DescriptorPoolBuilder()
472 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
473 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
474 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
475 
476 	m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
477 
478 	const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
479 
480 	DescriptorSetUpdateBuilder()
481 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
482 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
483 		.update(vk, device);
484 
485 	return *m_descriptorSetLayout;
486 }
487 
createInstance(Context & context) const488 TestInstance* SizeTest::createInstance (Context& context) const
489 {
490 	if (m_texture.type() == IMAGE_TYPE_BUFFER)
491 		return new BufferSizeTestInstance(context, m_texture, m_format);
492 	else
493 		return new ImageSizeTestInstance(context, m_texture, m_format);
494 }
495 
496 static const ImageType s_imageTypes[] =
497 {
498 	IMAGE_TYPE_1D,
499 	IMAGE_TYPE_1D_ARRAY,
500 	IMAGE_TYPE_2D,
501 	IMAGE_TYPE_2D_ARRAY,
502 	IMAGE_TYPE_3D,
503 	IMAGE_TYPE_CUBE,
504 	IMAGE_TYPE_CUBE_ARRAY,
505 	IMAGE_TYPE_BUFFER,
506 };
507 
508 //! Base sizes used to generate actual image/buffer sizes in the test.
509 static const tcu::IVec3 s_baseImageSizes[] =
510 {
511 	tcu::IVec3(32, 32, 32),
512 	tcu::IVec3(12, 34, 56),
513 	tcu::IVec3(1,   1,  1),
514 	tcu::IVec3(7,   1,  1),
515 };
516 
517 static const deUint32 s_flags[] =
518 {
519 	SizeTest::FLAG_READONLY_IMAGE,
520 	SizeTest::FLAG_WRITEONLY_IMAGE,
521 	SizeTest::FLAG_READONLY_IMAGE | SizeTest::FLAG_WRITEONLY_IMAGE,
522 };
523 
524 } // anonymous ns
525 
createImageSizeTests(tcu::TestContext & testCtx)526 tcu::TestCaseGroup* createImageSizeTests (tcu::TestContext& testCtx)
527 {
528 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "image_size", "imageSize() cases"));
529 
530 	const VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT;
531 
532 	for (int imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++imageTypeNdx)
533 	{
534 		de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(s_imageTypes[imageTypeNdx]).c_str(), ""));
535 
536 		for (int flagNdx = 0; flagNdx < DE_LENGTH_OF_ARRAY(s_flags); ++flagNdx)
537 		for (int imageSizeNdx = 0; imageSizeNdx < DE_LENGTH_OF_ARRAY(s_baseImageSizes); ++imageSizeNdx)
538 		{
539 			const Texture texture = getTexture(s_imageTypes[imageTypeNdx], s_baseImageSizes[imageSizeNdx]);
540 			imageGroup->addChild(new SizeTest(testCtx, getCaseName(texture, s_flags[flagNdx]), "", texture, format, s_flags[flagNdx]));
541 		}
542 
543 		testGroup->addChild(imageGroup.release());
544 	}
545 	return testGroup.release();
546 }
547 
548 } // image
549 } // vkt
550