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