1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 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 Buffer View Memory Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktApiBufferViewAccessTests.hpp"
26#include "vktApiBufferAndImageAllocationUtil.hpp"
27
28#include "deStringUtil.hpp"
29#include "deUniquePtr.hpp"
30#include "vktTestCase.hpp"
31#include "vktTestCaseUtil.hpp"
32#include "vkImageUtil.hpp"
33#include "vkMemUtil.hpp"
34#include "vkPrograms.hpp"
35#include "vkQueryUtil.hpp"
36#include "vkRef.hpp"
37#include "vkRefUtil.hpp"
38#include "vkTypeUtil.hpp"
39#include "vkCmdUtil.hpp"
40#include "vkObjUtil.hpp"
41#include "tcuImageCompare.hpp"
42#include "tcuTexture.hpp"
43#include "tcuTextureUtil.hpp"
44#include "deSharedPtr.hpp"
45#include "deArrayUtil.hpp"
46#include "tcuVectorUtil.hpp"
47#include "../image/vktImageTestsUtil.hpp"
48
49namespace vkt
50{
51
52namespace api
53{
54
55using namespace vk;
56
57namespace
58{
59
60enum AllocationKind
61{
62	ALLOCATION_KIND_SUBALLOCATION										= 0,
63	ALLOCATION_KIND_DEDICATED											= 1,
64	ALLOCATION_KIND_LAST
65};
66
67struct BufferViewCaseParams
68{
69	deUint32							bufferSize;
70	deUint32							bufferViewSize;
71	deUint32							elementOffset;
72	AllocationKind						bufferAllocationKind;
73	AllocationKind						imageAllocationKind;
74
75	VkFormat							format;
76	VkBufferUsageFlags					createUsage;
77	VkBufferUsageFlags					bindUsage;
78	VkFormatFeatureFlags				feature;
79	VkDescriptorType					descType;
80
81	BufferViewCaseParams (deUint32 bufferSize_,
82						  deUint32 bufferViewSize_,
83						  deUint32 elementOffset_,
84						  AllocationKind bufferAllocKind_,
85						  AllocationKind imageAllocKind_,
86						  VkFormat format_ = VK_FORMAT_R32_UINT,
87						  VkBufferUsageFlags createUsage_ = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
88						  VkBufferUsageFlags bindUsage_ = VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM,
89						  VkFormatFeatureFlags featureFlags_ = VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT,
90						  VkDescriptorType descType_ = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
91		: bufferSize(bufferSize_)
92		, bufferViewSize(bufferViewSize_)
93		, elementOffset(elementOffset_)
94		, bufferAllocationKind(bufferAllocKind_)
95		, imageAllocationKind(imageAllocKind_)
96		, format(format_)
97		, createUsage(createUsage_)
98		, bindUsage(bindUsage_)
99		, feature(featureFlags_)
100		, descType(descType_)
101	{
102	}
103};
104
105class BufferViewTestInstance : public vkt::TestInstance
106{
107public:
108										BufferViewTestInstance			(Context&					context,
109																		 BufferViewCaseParams		testCase);
110	virtual								~BufferViewTestInstance			(void);
111	virtual tcu::TestStatus				iterate							(void);
112
113private:
114	void								createQuad						(void);
115	tcu::TestStatus						checkResult						(deInt8						factor);
116
117private:
118	BufferViewCaseParams				m_testCase;
119
120	const tcu::IVec2					m_renderSize;
121	const VkFormat						m_colorFormat;
122
123	const VkDeviceSize					m_pixelDataSize;
124
125	Move<VkImage>						m_colorImage;
126	de::MovePtr<Allocation>				m_colorImageAlloc;
127	Move<VkImageView>					m_colorAttachmentView;
128	Move<VkRenderPass>					m_renderPass;
129	Move<VkFramebuffer>					m_framebuffer;
130
131	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
132	Move<VkDescriptorPool>				m_descriptorPool;
133	Move<VkDescriptorSet>				m_descriptorSet;
134
135	Move<VkBuffer>						m_uniformBuffer;
136	de::MovePtr<vk::Allocation>			m_uniformBufferAlloc;
137	Move<VkBufferView>					m_uniformBufferView;
138
139	Move<VkShaderModule>				m_vertexShaderModule;
140	Move<VkShaderModule>				m_fragmentShaderModule;
141
142	Move<VkBuffer>						m_vertexBuffer;
143	std::vector<tcu::Vec4>				m_vertices;
144	de::MovePtr<Allocation>				m_vertexBufferAlloc;
145
146	Move<VkPipelineLayout>				m_pipelineLayout;
147	Move<VkPipeline>					m_graphicsPipelines;
148
149	Move<VkCommandPool>					m_cmdPool;
150	Move<VkCommandBuffer>				m_cmdBuffer;
151
152	Move<VkBuffer>						m_resultBuffer;
153	de::MovePtr<Allocation>				m_resultBufferAlloc;
154};
155
156static void generateBuffer												(std::vector<deUint32>&		uniformData,
157																		 deUint32					bufferSize,
158																		 deInt8						factor)
159{
160	for (deUint32 i = 0; i < bufferSize; ++i)
161		uniformData.push_back(factor * i);
162}
163
164void BufferViewTestInstance::createQuad									(void)
165{
166	tcu::Vec4							a(-1.0, -1.0, 0.0, 1.0);
167	tcu::Vec4							b(1.0, -1.0, 0.0, 1.0);
168	tcu::Vec4							c(1.0, 1.0, 0.0, 1.0);
169	tcu::Vec4							d(-1.0, 1.0, 0.0, 1.0);
170
171	// Triangle 1
172	m_vertices.push_back(a);
173	m_vertices.push_back(c);
174	m_vertices.push_back(b);
175
176	// Triangle 2
177	m_vertices.push_back(c);
178	m_vertices.push_back(a);
179	m_vertices.push_back(d);
180}
181
182BufferViewTestInstance::~BufferViewTestInstance							(void)
183{
184}
185
186BufferViewTestInstance::BufferViewTestInstance							(Context&					context,
187																		 BufferViewCaseParams		testCase)
188										: vkt::TestInstance				(context)
189										, m_testCase					(testCase)
190										, m_renderSize					(testCase.bufferViewSize, testCase.bufferViewSize)
191										, m_colorFormat					(VK_FORMAT_R32_UINT)
192										, m_pixelDataSize				(m_renderSize.x() * m_renderSize.y() * mapVkFormat(m_colorFormat).getPixelSize())
193{
194	const DeviceInterface&				vk								= context.getDeviceInterface();
195	const VkDevice						vkDevice						= context.getDevice();
196	const deUint32						queueFamilyIndex				= context.getUniversalQueueFamilyIndex();
197	SimpleAllocator						memAlloc						(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
198	const VkComponentMapping			channelMappingRGBA				= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
199
200	// Create color image
201	if (m_testCase.imageAllocationKind == ALLOCATION_KIND_DEDICATED)
202	{
203		ImageDedicatedAllocation().createTestImage(m_renderSize, m_colorFormat, context, memAlloc, m_colorImage, MemoryRequirement::Any, m_colorImageAlloc);
204	}
205	else
206	{
207		ImageSuballocation().createTestImage(m_renderSize, m_colorFormat, context, memAlloc, m_colorImage, MemoryRequirement::Any, m_colorImageAlloc);
208	}
209
210	// Create destination buffer
211	if (m_testCase.bufferAllocationKind == ALLOCATION_KIND_DEDICATED)
212	{
213		BufferDedicatedAllocation().createTestBuffer(vk, vkDevice, queueFamilyIndex, m_pixelDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, m_context, memAlloc, m_resultBuffer, MemoryRequirement::HostVisible, m_resultBufferAlloc);
214	}
215	else
216	{
217		BufferSuballocation().createTestBuffer(vk, vkDevice, queueFamilyIndex, m_pixelDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, m_context, memAlloc, m_resultBuffer, MemoryRequirement::HostVisible, m_resultBufferAlloc);
218	}
219
220	// Create color attachment view
221	{
222		const VkImageViewCreateInfo		colorAttachmentViewParams		=
223		{
224			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,					// VkStructureType			sType;
225			DE_NULL,													// const void*				pNext;
226			0u,															// VkImageViewCreateFlags	flags;
227			*m_colorImage,												// VkImage					image;
228			VK_IMAGE_VIEW_TYPE_2D,										// VkImageViewType			viewType;
229			m_colorFormat,												// VkFormat					format;
230			channelMappingRGBA,											// VkChannelMapping			channels;
231			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },				// VkImageSubresourceRange	subresourceRange;
232		};
233
234		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
235	}
236
237	// Create render pass
238	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
239
240	// Create framebuffer
241	{
242		const VkImageView				attachmentBindInfos[1]			=
243		{
244			*m_colorAttachmentView,
245		};
246
247		const VkFramebufferCreateInfo	framebufferParams				=
248		{
249			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,					// VkStructureType			sType;
250			DE_NULL,													// const void*				pNext;
251			(VkFramebufferCreateFlags)0,
252			*m_renderPass,												// VkRenderPass				renderPass;
253			1u,															// deUint32					attachmentCount;
254			attachmentBindInfos,										// const VkImageView*		pAttachments;
255			(deUint32)m_renderSize.x(),									// deUint32					width;
256			(deUint32)m_renderSize.y(),									// deUint32					height;
257			1u															// deUint32					layers;
258		};
259
260		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
261	}
262
263	// Create descriptors
264	{
265		const VkDescriptorSetLayoutBinding
266										layoutBindings[1]				=
267		{
268			{
269				0u,														// deUint32					binding;
270				VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,				// VkDescriptorType			descriptorType;
271				1u,														// deUint32					arraySize;
272				VK_SHADER_STAGE_ALL,									// VkShaderStageFlags		stageFlags;
273				DE_NULL													// const VkSampler*			pImmutableSamplers;
274			},
275		};
276
277		const VkDescriptorSetLayoutCreateInfo
278										descriptorLayoutParams			=
279		{
280			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType			sType;
281			DE_NULL,													// const void*				pNext;
282			(VkDescriptorSetLayoutCreateFlags)0,
283			DE_LENGTH_OF_ARRAY(layoutBindings),							// deUint32					count;
284			layoutBindings												// const VkDescriptorSetLayoutBinding pBinding;
285		};
286
287		m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorLayoutParams);
288
289		// Generate buffer
290		std::vector<deUint32>			uniformData;
291		generateBuffer(uniformData, testCase.bufferSize, 1);
292
293		const VkDeviceSize				uniformSize						= testCase.bufferSize * sizeof(deUint32);
294
295		BufferSuballocation().createTestBuffer(vk, vkDevice, queueFamilyIndex, uniformSize, testCase.createUsage, m_context, memAlloc, m_uniformBuffer, MemoryRequirement::HostVisible, m_uniformBufferAlloc);
296		deMemcpy(m_uniformBufferAlloc->getHostPtr(), uniformData.data(), (size_t)uniformSize);
297		flushAlloc(vk, vkDevice, *m_uniformBufferAlloc);
298
299		const VkBufferViewCreateInfo	viewInfo						=
300		{
301			VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,					// VkStructureType			sType;
302			DE_NULL,													// void*					pNext;
303			(VkBufferViewCreateFlags)0,
304			*m_uniformBuffer,											// VkBuffer					buffer;
305			m_colorFormat,												// VkFormat					format;
306			m_testCase.elementOffset * sizeof(deUint32),				// VkDeviceSize				offset;
307			m_testCase.bufferViewSize * sizeof(deUint32)				// VkDeviceSize				range;
308		};
309
310		m_uniformBufferView = createBufferView(vk, vkDevice, &viewInfo);
311
312		const VkDescriptorPoolSize		descriptorTypes[1]				=
313		{
314			{
315				VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,				// VkDescriptorType			type;
316				1														// deUint32					count;
317			}
318		};
319
320		const VkDescriptorPoolCreateInfo
321										descriptorPoolParams			=
322		{
323			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,				// VkStructureType			sType;
324			DE_NULL,													// void*					pNext;
325			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,			// VkDescriptorPoolCreateFlags flags;
326			1u,															// uint32_t					maxSets;
327			DE_LENGTH_OF_ARRAY(descriptorTypes),						// deUint32					count;
328			descriptorTypes												// const VkDescriptorTypeCount* pTypeCount
329		};
330
331		m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolParams);
332
333		const VkDescriptorSetAllocateInfo
334										descriptorSetParams				=
335		{
336			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
337			DE_NULL,
338			*m_descriptorPool,
339			1u,
340			&m_descriptorSetLayout.get(),
341		};
342		m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetParams);
343
344		const VkWriteDescriptorSet		writeDescritporSets[]			=
345		{
346			{
347				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,					// VkStructureType			sType;
348				DE_NULL,												// const void*				pNext;
349				*m_descriptorSet,										// VkDescriptorSet			destSet;
350				0,														// deUint32					destBinding;
351				0,														// deUint32					destArrayElement;
352				1u,														// deUint32					count;
353				VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,				// VkDescriptorType			descriptorType;
354				(const VkDescriptorImageInfo*)DE_NULL,
355				(const VkDescriptorBufferInfo*)DE_NULL,
356				&m_uniformBufferView.get(),
357			}
358		};
359
360		vk.updateDescriptorSets(vkDevice, DE_LENGTH_OF_ARRAY(writeDescritporSets), writeDescritporSets, 0u, DE_NULL);
361	}
362
363	// Create pipeline layout
364	{
365		const VkPipelineLayoutCreateInfo
366										pipelineLayoutParams			=
367		{
368			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// VkStructureType			sType;
369			DE_NULL,													// const void*				pNext;
370			(VkPipelineLayoutCreateFlags)0,
371			1u,															// deUint32					descriptorSetCount;
372			&*m_descriptorSetLayout,									// const VkDescriptorSetLayout* pSetLayouts;
373			0u,															// deUint32					pushConstantRangeCount;
374			DE_NULL														// const VkPushConstantRange* pPushConstantRanges;
375		};
376
377		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
378	}
379
380	// Create shaders
381	{
382		m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
383		m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
384	}
385
386	// Create pipeline
387	{
388		const std::vector<VkViewport>	viewports	(1, makeViewport(m_renderSize));
389		const std::vector<VkRect2D>		scissors	(1, makeRect2D(m_renderSize));
390
391		m_graphicsPipelines = makeGraphicsPipeline(vk,						// const DeviceInterface&            vk
392												   vkDevice,				// const VkDevice                    device
393												   *m_pipelineLayout,		// const VkPipelineLayout            pipelineLayout
394												   *m_vertexShaderModule,	// const VkShaderModule              vertexShaderModule
395												   DE_NULL,					// const VkShaderModule              tessellationControlModule
396												   DE_NULL,					// const VkShaderModule              tessellationEvalModule
397												   DE_NULL,					// const VkShaderModule              geometryShaderModule
398												   *m_fragmentShaderModule,	// const VkShaderModule              fragmentShaderModule
399												   *m_renderPass,			// const VkRenderPass                renderPass
400												   viewports,				// const std::vector<VkViewport>&    viewports
401												   scissors);				// const std::vector<VkRect2D>&      scissors
402	}
403
404	// Create vertex buffer
405	{
406		createQuad();
407		const VkDeviceSize				vertexDataSize					= m_vertices.size() * sizeof(tcu::Vec4);
408
409		BufferSuballocation().createTestBuffer(vk, vkDevice, queueFamilyIndex, vertexDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, m_context, memAlloc, m_vertexBuffer, MemoryRequirement::HostVisible, m_vertexBufferAlloc);
410
411		// Load vertices into vertex buffer
412		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), (size_t)vertexDataSize);
413		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
414	}
415
416	// Create command pool
417	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
418
419	// Create command buffer
420	{
421		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
422
423		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
424
425		const VkImageMemoryBarrier		initialImageBarrier				=
426		{
427			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
428			DE_NULL,													// const void*				pNext;
429			0,															// VkAccessFlags			srcAccessMask;
430			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,						// VkAccessFlags			dstAccessMask;
431			VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			oldLayout;
432			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout			newLayout;
433			VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
434			VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
435			*m_colorImage,												// VkImage					image;
436			{															// VkImageSubresourceRange	subresourceRange;
437				VK_IMAGE_ASPECT_COLOR_BIT,								// VkImageAspectFlags		aspectMask;
438				0u,														// deUint32					baseMipLevel;
439				1u,														// deUint32					mipLevels;
440				0u,														// deUint32					baseArraySlice;
441				1u														// deUint32					arraySize;
442			}
443		};
444
445		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &initialImageBarrier);
446
447		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), tcu::Vec4(0.0f));
448
449		const VkDeviceSize				vertexBufferOffset[1]			= { 0 };
450
451		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
452		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &*m_descriptorSet, 0u, DE_NULL);
453		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), vertexBufferOffset);
454		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
455		endRenderPass(vk, *m_cmdBuffer);
456		copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, *m_resultBuffer, m_renderSize);
457		endCommandBuffer(vk, *m_cmdBuffer);
458	}
459}
460
461tcu::TestStatus BufferViewTestInstance::checkResult						(deInt8						factor)
462{
463	const DeviceInterface&				vk								= m_context.getDeviceInterface();
464	const VkDevice						vkDevice						= m_context.getDevice();
465	const tcu::TextureFormat			tcuFormat						= mapVkFormat(m_colorFormat);
466	de::MovePtr<tcu::TextureLevel>		resultLevel						(new tcu::TextureLevel(tcuFormat, m_renderSize.x(), m_renderSize.y()));
467
468	invalidateAlloc(vk, vkDevice, *m_resultBufferAlloc);
469	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_resultBufferAlloc->getHostPtr()));
470
471	tcu::ConstPixelBufferAccess			pixelBuffer						= resultLevel->getAccess();
472	for (deInt32 i = 0; i < (deInt32) m_renderSize.x(); ++i)
473	{
474		tcu::IVec4						pixel							= pixelBuffer.getPixelInt(i, i);
475		deInt32							expected						= factor * (m_testCase.elementOffset + i);
476		deInt32							actual							= pixel[0];
477		if (expected != actual)
478		{
479			std::ostringstream			errorMessage;
480			errorMessage << "BufferView test failed. expected: " << expected << " actual: " << actual;
481			return tcu::TestStatus::fail(errorMessage.str());
482		}
483	}
484
485	return tcu::TestStatus::pass("BufferView test");
486}
487
488tcu::TestStatus BufferViewTestInstance::iterate							(void)
489{
490	const DeviceInterface&				vk								= m_context.getDeviceInterface();
491	const VkDevice						vkDevice						= m_context.getDevice();
492	const VkQueue						queue							= m_context.getUniversalQueue();
493
494	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
495
496	tcu::TestStatus						testStatus						= checkResult(1);
497	if (testStatus.getCode() != QP_TEST_RESULT_PASS)
498		return testStatus;
499
500	// Generate and bind another buffer
501	std::vector<deUint32>				uniformData;
502	const VkDeviceSize					uniformSize						= m_testCase.bufferSize * sizeof(deUint32);
503	const deInt8						factor							= 2;
504
505	generateBuffer(uniformData, m_testCase.bufferSize, factor);
506	deMemcpy(m_uniformBufferAlloc->getHostPtr(), uniformData.data(), (size_t)uniformSize);
507	flushAlloc(vk, vkDevice, *m_uniformBufferAlloc);
508
509	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
510
511	return checkResult(factor);
512}
513
514class BufferViewTestCase : public vkt::TestCase
515{
516public:
517									BufferViewTestCase					(tcu::TestContext&			testCtx,
518																		 const std::string&			name,
519																		 BufferViewCaseParams		bufferViewTestInfo)
520									: vkt::TestCase						(testCtx, name)
521									, m_bufferViewTestInfo				(bufferViewTestInfo)
522	{}
523
524	virtual							~BufferViewTestCase					(void)
525	{}
526	virtual	void					initPrograms						(SourceCollections&			programCollection) const;
527
528	virtual TestInstance*			createInstance						(Context&					context) const
529	{
530		return new BufferViewTestInstance(context, m_bufferViewTestInfo);
531	}
532private:
533	BufferViewCaseParams			m_bufferViewTestInfo;
534};
535
536void BufferViewTestCase::initPrograms									(SourceCollections&			programCollection) const
537{
538	programCollection.glslSources.add("vert") << glu::VertexSource(
539		"#version 310 es\n"
540		"layout (location = 0) in highp vec4 a_position;\n"
541		"void main()\n"
542		"{\n"
543		"	gl_Position = a_position;\n"
544		"}\n");
545
546
547	programCollection.glslSources.add("frag") << glu::FragmentSource(
548		"#version 310 es\n"
549		"#extension GL_EXT_texture_buffer : enable\n"
550		"layout (set=0, binding=0) uniform highp utextureBuffer u_buffer;\n"
551		"layout (location = 0) out highp uint o_color;\n"
552		"void main()\n"
553		"{\n"
554		"	o_color = texelFetch(u_buffer, int(gl_FragCoord.x)).x;\n"
555		"}\n");
556}
557
558class BufferViewAllFormatsTestInstance : public vkt::TestInstance
559{
560public:
561										BufferViewAllFormatsTestInstance		(Context&					context,
562																				 BufferViewCaseParams		testCase);
563	virtual								~BufferViewAllFormatsTestInstance		(void);
564	virtual tcu::TestStatus				iterate									(void);
565
566private:
567	void								checkTexelBufferSupport					(Context&					context,
568																				 VkFormat					format,
569																				 BufferViewCaseParams		testCase);
570	int									getFetchPos								(int fetchPosNdx);
571	tcu::TestStatus						checkResult								();
572	tcu::TestStatus						checkResultFloat						();
573	void								populateSourceBuffer					(const tcu::PixelBufferAccess& access, deUint32 bufferNdx);
574
575private:
576	enum
577	{
578		// some arbitrary points
579		SAMPLE_POINT_0 = 6,
580		SAMPLE_POINT_1 = 51,
581		SAMPLE_POINT_2 = 42,
582		SAMPLE_POINT_3 = 25,
583	};
584
585	BufferViewCaseParams				m_testCase;
586	const VkFormat						m_bufferFormat;
587
588	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
589	Move<VkDescriptorPool>				m_descriptorPool;
590	Move<VkDescriptorSet>				m_descriptorSet;
591
592	Move<VkBuffer>						m_uniformBuffer;
593	de::MovePtr<vk::Allocation>			m_uniformBufferAlloc;
594	Move<VkBufferView>					m_uniformBufferView;
595	Move<VkShaderModule>				m_computeShaderModule;
596	Move<VkPipelineLayout>				m_pipelineLayout;
597	Move<VkPipeline>					m_computePipeline;
598
599	Move<VkCommandPool>					m_cmdPool;
600	Move<VkCommandBuffer>				m_cmdBuffer;
601
602	Move<VkBuffer>						m_resultBuffer;
603	de::MovePtr<Allocation>				m_resultBufferAlloc;
604
605	de::ArrayBuffer<deUint8>			m_sourceBuffer;
606	tcu::ConstPixelBufferAccess			m_sourceView;
607};
608
609void BufferViewAllFormatsTestInstance::checkTexelBufferSupport			(Context& context, VkFormat format, BufferViewCaseParams testCase)
610{
611	const InstanceInterface&	vki				= context.getInstanceInterface();
612	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
613
614	VkFormatProperties					properties;
615	properties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
616
617	if (!(properties.bufferFeatures & testCase.feature))
618		TCU_THROW(NotSupportedError, "Format not supported");
619
620#ifndef CTS_USES_VULKANSC
621	if(testCase.bindUsage != VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM)
622	{
623		if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance5"))
624			TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance5 not supported");
625	}
626#endif
627}
628
629BufferViewAllFormatsTestInstance::~BufferViewAllFormatsTestInstance		(void)
630{
631}
632
633/* Taken from BindingShaderAccessTests.cpp */
634void BufferViewAllFormatsTestInstance::populateSourceBuffer				(const tcu::PixelBufferAccess& access, deUint32 bufferNdx)
635{
636	DE_ASSERT(access.getHeight() == 1);
637	DE_ASSERT(access.getDepth() == 1);
638
639	const deInt32 width = access.getWidth();
640
641	for (int x = 0; x < width; ++x)
642	{
643		int	red		= 255 * x / width;												//!< gradient from 0 -> max (detects large offset errors)
644		int	green	= ((x % 2 == 0) ? (127) : (0)) + ((x % 4 < 3) ? (128) : (0));	//!< 3-level M pattern (detects small offset errors)
645		int	blue	= 16 * (x % 16);												//!< 16-long triangle wave
646
647		DE_ASSERT(de::inRange(red, 0, 255));
648		DE_ASSERT(de::inRange(green, 0, 255));
649		DE_ASSERT(de::inRange(blue, 0, 255));
650
651		if (bufferNdx % 2 == 0) red		= 255 - red;
652		if (bufferNdx % 3 == 0) green	= 255 - green;
653		if (bufferNdx % 4 == 0) blue	= 255 - blue;
654
655		access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0);
656	}
657}
658
659BufferViewAllFormatsTestInstance::BufferViewAllFormatsTestInstance		(Context&					context,
660																		 BufferViewCaseParams		testCase)
661										: vkt::TestInstance				(context)
662										, m_testCase					(testCase)
663										, m_bufferFormat				(testCase.format)
664{
665	const DeviceInterface&				vk								= context.getDeviceInterface();
666	const VkDevice						vkDevice						= context.getDevice();
667	const deUint32						queueFamilyIndex				= context.getUniversalQueueFamilyIndex();
668	SimpleAllocator						memAlloc						(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
669
670	checkTexelBufferSupport(context, m_bufferFormat, testCase);
671
672	// Create a result buffer
673	BufferSuballocation().createTestBuffer(vk, vkDevice, queueFamilyIndex, sizeof(tcu::Vec4[4]), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, m_context, memAlloc, m_resultBuffer, MemoryRequirement::HostVisible, m_resultBufferAlloc);
674
675	// Create descriptors
676	{
677		const VkDescriptorSetLayoutBinding layoutBindings[2]			=
678		{
679			{
680				0u,														// deUint32					binding;
681				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,						// VkDescriptorType			descriptorType;
682				1u,														// deUint32					arraySize;
683				VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlags		stageFlags;
684				DE_NULL													// const VkSampler*			pImmutableSamplers;
685			},
686			{
687				1u,														// deUint32					binding;
688				testCase.descType,										// VkDescriptorType			descriptorType;
689				1u,														// deUint32					arraySize;
690				VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlags		stageFlags;
691				DE_NULL													// const VkSampler*			pImmutableSamplers;
692			},
693		};
694
695		const VkDescriptorSetLayoutCreateInfo descriptorLayoutParams	=
696		{
697			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType			sType;
698			DE_NULL,													// const void*				pNext;
699			(VkDescriptorSetLayoutCreateFlags)0,
700			DE_LENGTH_OF_ARRAY(layoutBindings),							// deUint32					count;
701			layoutBindings												// const VkDescriptorSetLayoutBinding pBinding;
702		};
703
704		m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorLayoutParams);
705
706
707		// Generate buffer
708		const tcu::TextureFormat tcuFormat	= mapVkFormat(m_bufferFormat);
709
710		de::ArrayBuffer<deUint8> sourceBuffer(testCase.bufferSize);
711		populateSourceBuffer(tcu::PixelBufferAccess(tcuFormat, tcu::IVec3(testCase.bufferSize / tcuFormat.getPixelSize(), 1, 1), sourceBuffer.getPtr()), 0);
712
713		m_sourceBuffer = sourceBuffer;
714		m_sourceView = tcu::ConstPixelBufferAccess(tcuFormat, tcu::IVec3(64, 1, 1), m_sourceBuffer.getPtr());
715
716		BufferSuballocation().createTestBuffer(vk, vkDevice, queueFamilyIndex, sourceBuffer.size(), testCase.createUsage, m_context, memAlloc, m_uniformBuffer, MemoryRequirement::HostVisible, m_uniformBufferAlloc);
717		deMemcpy(m_uniformBufferAlloc->getHostPtr(), sourceBuffer.getPtr(), sourceBuffer.size());
718		flushAlloc(vk, vkDevice, *m_uniformBufferAlloc);
719
720		VkBufferViewCreateInfo	viewInfo								=
721		{
722			VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,					// VkStructureType			sType;
723			DE_NULL,													// void*					pNext;
724			(VkBufferViewCreateFlags)0,
725			*m_uniformBuffer,											// VkBuffer					buffer;
726			m_bufferFormat,												// VkFormat					format;
727			m_testCase.elementOffset,									// VkDeviceSize				offset;
728			VK_WHOLE_SIZE												// VkDeviceSize				range;
729		};
730
731#ifndef CTS_USES_VULKANSC
732		VkBufferUsageFlags2CreateInfoKHR bindUsageInfo;
733		if (testCase.bindUsage != VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM)
734		{
735			bindUsageInfo.sType	= VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR;	// VkStructureType			sType;
736			bindUsageInfo.pNext	= DE_NULL;													// const void*				pNext;
737			bindUsageInfo.usage	= testCase.bindUsage;										// VkBufferUsageFlags2KHR	usage;
738
739			viewInfo.pNext		= &bindUsageInfo;
740		}
741#endif
742
743		m_uniformBufferView = createBufferView(vk, vkDevice, &viewInfo);
744
745		const VkDescriptorPoolSize		descriptorTypes[2]				=
746		{
747			{
748				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,						// VkDescriptorType			type;
749				1														// deUint32					count;
750			},
751			{
752				testCase.descType,										// VkDescriptorType			type;
753				1														// deUint32					count;
754			}
755		};
756
757		const VkDescriptorPoolCreateInfo
758										descriptorPoolParams			=
759		{
760			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,				// VkStructureType			sType;
761			DE_NULL,													// void*					pNext;
762			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,			// VkDescriptorPoolCreateFlags flags;
763			1u,															// uint32_t					maxSets;
764			DE_LENGTH_OF_ARRAY(descriptorTypes),						// deUint32					count;
765			descriptorTypes												// const VkDescriptorTypeCount* pTypeCount
766		};
767
768		m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolParams);
769
770		const VkDescriptorSetAllocateInfo
771										descriptorSetParams				=
772		{
773			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
774			DE_NULL,
775			*m_descriptorPool,
776			1u,
777			&m_descriptorSetLayout.get(),
778		};
779		m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetParams);
780
781		const VkDescriptorBufferInfo	outBufferInfo					=
782		{
783			m_resultBuffer.get(),
784			0,
785			sizeof(tcu::Vec4[4])
786		};
787
788		const VkWriteDescriptorSet		writeDescritporSets[]			=
789		{
790			{
791				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,					// VkStructureType			sType;
792				DE_NULL,												// const void*				pNext;
793				*m_descriptorSet,										// VkDescriptorSet			destSet;
794				0,														// deUint32					destBinding;
795				0,														// deUint32					destArrayElement;
796				1u,														// deUint32					count;
797				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,						// VkDescriptorType			descriptorType;
798				(const VkDescriptorImageInfo*)DE_NULL,
799				&outBufferInfo,
800				(const VkBufferView*)DE_NULL,
801			},
802			{
803				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,					// VkStructureType			sType;
804				DE_NULL,												// const void*				pNext;
805				*m_descriptorSet,										// VkDescriptorSet			destSet;
806				1,														// deUint32					destBinding;
807				0,														// deUint32					destArrayElement;
808				1u,														// deUint32					count;
809				testCase.descType,										// VkDescriptorType			descriptorType;
810				(const VkDescriptorImageInfo*)DE_NULL,
811				(const VkDescriptorBufferInfo*)DE_NULL,
812				&m_uniformBufferView.get(),
813			}
814		};
815
816		vk.updateDescriptorSets(vkDevice, DE_LENGTH_OF_ARRAY(writeDescritporSets), writeDescritporSets, 0u, DE_NULL);
817	}
818
819	// Create pipeline layout
820	{
821		const VkPipelineLayoutCreateInfo pipelineLayoutParams			=
822		{
823			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// VkStructureType			sType;
824			DE_NULL,													// const void*				pNext;
825			(VkPipelineLayoutCreateFlags)0,
826			1u,															// deUint32					descriptorSetCount;
827			&*m_descriptorSetLayout,									// const VkDescriptorSetLayout* pSetLayouts;
828			0u,															// deUint32					pushConstantRangeCount;
829			DE_NULL														// const VkPushConstantRange* pPushConstantRanges;
830		};
831
832		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
833	}
834
835	// Create shaders
836	{
837		m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("comp"), 0);
838	}
839
840	// Create pipeline
841	{
842		m_computePipeline         = makeComputePipeline(vk, vkDevice, m_pipelineLayout.get(), m_computeShaderModule.get());
843	}
844
845	// Create command pool
846	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
847
848	// Create and record a command buffer
849	{
850		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
851
852		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
853
854		vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
855		vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, nullptr);
856
857		const vk::VkBufferMemoryBarrier	barrier		=
858		{
859			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
860			DE_NULL,
861			vk::VK_ACCESS_HOST_WRITE_BIT,			// srcAccessMask
862			vk::VK_ACCESS_UNIFORM_READ_BIT,			// dstAccessMask
863			VK_QUEUE_FAMILY_IGNORED,				// srcQueueFamilyIndex
864			VK_QUEUE_FAMILY_IGNORED,				// destQueueFamilyIndex
865			*m_resultBuffer,						// buffer
866			0u,										// offset
867			sizeof(tcu::Vec4[4]),					// size
868		};
869		const vk::VkBufferMemoryBarrier bufferBarrier =
870		{
871			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
872			DE_NULL,
873			vk::VK_ACCESS_SHADER_WRITE_BIT,			// srcAccessMask
874			vk::VK_ACCESS_HOST_READ_BIT,			// dstAccessMask
875			VK_QUEUE_FAMILY_IGNORED,				// srcQueueFamilyIndex
876			VK_QUEUE_FAMILY_IGNORED,				// destQueueFamilyIndex
877			*m_resultBuffer,						// buffer
878			(vk::VkDeviceSize)0u,					// offset
879			sizeof(tcu::Vec4[4]),					// size
880		};
881
882		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, &barrier, 0u, nullptr);
883		//vk.cmdDispatch(*m_cmdBuffer, 1u, 1u, 1u);
884		vk.cmdDispatch(*m_cmdBuffer, 4u, 1u, 1u);
885		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 0u, &bufferBarrier, 0u, nullptr);
886		endCommandBuffer(vk, *m_cmdBuffer);
887	}
888}
889
890int BufferViewAllFormatsTestInstance::getFetchPos (int fetchPosNdx)
891{
892	static const int fetchPositions[4] =
893	{
894		SAMPLE_POINT_0,
895		SAMPLE_POINT_1,
896		SAMPLE_POINT_2,
897		SAMPLE_POINT_3,
898	};
899
900	return fetchPositions[fetchPosNdx];
901}
902
903tcu::TestStatus BufferViewAllFormatsTestInstance::checkResult						()
904{
905	const DeviceInterface&				vk					= m_context.getDeviceInterface();
906	const VkDevice						vkDevice			= m_context.getDevice();
907	bool								allResultsOk		= true;
908
909	tcu::UVec4							results[4];
910	invalidateAlloc(vk, vkDevice, *m_resultBufferAlloc);
911	deMemcpy(results, m_resultBufferAlloc->getHostPtr(), sizeof(tcu::UVec4[4]));
912
913	// verify
914	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
915	{
916		const tcu::UVec4	result				= results[resultNdx];
917		const tcu::UVec4	conversionThreshold	= tcu::UVec4(0);
918		tcu::UVec4			reference			= tcu::UVec4(0);
919
920		reference	+= m_sourceView.getPixelUint(getFetchPos(resultNdx), 0, 0);
921
922		if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
923		{
924			allResultsOk = false;
925
926			m_context.getTestContext().getLog()
927				<< tcu::TestLog::Message
928				<< "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
929				<< tcu::TestLog::EndMessage;
930		}
931	}
932
933	if (allResultsOk)
934		return tcu::TestStatus::pass("Pass");
935	else
936		return tcu::TestStatus::fail("Invalid result values");
937}
938
939tcu::TestStatus BufferViewAllFormatsTestInstance::checkResultFloat					()
940{
941	const DeviceInterface&				vk					= m_context.getDeviceInterface();
942	const VkDevice						vkDevice			= m_context.getDevice();
943	bool								allResultsOk		= true;
944
945	tcu::Vec4							results[4];
946	invalidateAlloc(vk, vkDevice, *m_resultBufferAlloc);
947	deMemcpy(results, m_resultBufferAlloc->getHostPtr(), sizeof(tcu::Vec4[4]));
948
949	// verify
950	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
951	{
952		const tcu::Vec4	result				= results[resultNdx];
953		const tcu::Vec4	conversionThreshold	= tcu::Vec4(1.0f / 255.0f);
954		tcu::Vec4		reference			= tcu::Vec4(0.0f);
955
956		reference	+= m_sourceView.getPixel(getFetchPos(resultNdx), 0, 0);
957
958		if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
959		{
960			allResultsOk = false;
961
962			m_context.getTestContext().getLog()
963				<< tcu::TestLog::Message
964				<< "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
965				<< tcu::TestLog::EndMessage;
966		}
967	}
968
969	if (allResultsOk)
970		return tcu::TestStatus::pass("Pass");
971	else
972		return tcu::TestStatus::fail("Invalid result values");
973}
974
975tcu::TestStatus BufferViewAllFormatsTestInstance::iterate							(void)
976{
977	const DeviceInterface&				vk					= m_context.getDeviceInterface();
978	const VkDevice						vkDevice			= m_context.getDevice();
979	const VkQueue						queue				= m_context.getUniversalQueue();
980
981	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
982
983	if (isIntFormat(m_bufferFormat) || isUintFormat(m_bufferFormat))
984		return checkResult();
985	else
986		return checkResultFloat();
987}
988
989
990class BufferViewAllFormatsTestCase : public vkt::TestCase
991{
992public:
993									BufferViewAllFormatsTestCase		(tcu::TestContext&			testCtx,
994																		 const std::string&			name,
995																		 BufferViewCaseParams		bufferViewTestInfo)
996									: vkt::TestCase						(testCtx, name)
997									, m_bufferViewTestInfo				(bufferViewTestInfo)
998	{}
999
1000	virtual							~BufferViewAllFormatsTestCase		(void)
1001	{}
1002	virtual	void					initPrograms						(SourceCollections&			programCollection) const;
1003	virtual void					checkSupport						(Context&					context) const
1004	{
1005		const InstanceInterface&	vki				= context.getInstanceInterface();
1006		const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
1007
1008#ifndef CTS_USES_VULKANSC
1009		if ((m_bufferViewTestInfo.format == VK_FORMAT_A8_UNORM_KHR) ||
1010			(m_bufferViewTestInfo.format == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR))
1011			context.requireDeviceFunctionality("VK_KHR_maintenance5");
1012#endif // CTS_USES_VULKANSC
1013
1014		if ((m_bufferViewTestInfo.createUsage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) != 0)
1015		{
1016			VkFormatProperties					properties;
1017			properties = getPhysicalDeviceFormatProperties(vki, physicalDevice, m_bufferViewTestInfo.format);
1018			if ((properties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) == 0)
1019			{
1020				TCU_THROW(NotSupportedError, "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT not supported for format");
1021			}
1022		}
1023	}
1024
1025	virtual TestInstance*			createInstance						(Context&					context) const
1026	{
1027		return new BufferViewAllFormatsTestInstance(context, m_bufferViewTestInfo);
1028	}
1029
1030private:
1031	BufferViewCaseParams			m_bufferViewTestInfo;
1032};
1033
1034const std::string strLayoutFormat										(VkFormat format)
1035{
1036	std::ostringstream	buf;
1037
1038	buf << ", " << image::getShaderImageFormatQualifier(mapVkFormat(format)).c_str();
1039
1040	return buf.str();
1041}
1042
1043void BufferViewAllFormatsTestCase::initPrograms							(SourceCollections&			programCollection) const
1044{
1045	std::ostringstream	buf;
1046
1047	const bool			isIntFmt		= isIntFormat(m_bufferViewTestInfo.format);
1048	const bool			isUintFmt		= isUintFormat(m_bufferViewTestInfo.format);
1049
1050	bool				isUniform;
1051	if (m_bufferViewTestInfo.bindUsage != VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM)
1052	{
1053		isUniform = m_bufferViewTestInfo.bindUsage == VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT ? true : false;
1054	}
1055	else
1056	{
1057		isUniform = m_bufferViewTestInfo.createUsage == VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT ? true : false;
1058	}
1059	const char* const	storageType		= isUniform ? "textureBuffer " : "imageBuffer ";
1060	const char* const	extraOption		= isUniform ? "" : "readonly ";
1061	const std::string	stringFmtLayout = isUniform ? "" : strLayoutFormat(m_bufferViewTestInfo.format);
1062	const char* const	fmtLayout		= isUniform ? "" : stringFmtLayout.c_str();
1063	const char* const	opName			= isUniform ? "texelFetch" : "imageLoad";
1064	const char* const	outFormat		= isIntFmt  ? "i"			   : isUintFmt ? "u" : "";
1065	const char* const	inFormat		= vk::isScaledFormat(m_bufferViewTestInfo.format)? "" : outFormat;
1066
1067	buf << "#version 440\n"
1068		<< "#extension GL_EXT_texture_buffer : require\n"
1069		<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1070		<< "layout(set = 0, binding = 1" << fmtLayout << ") uniform highp " << extraOption << inFormat << storageType << " texelBuffer;\n"
1071		<< "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
1072		<< "{\n"
1073		<< "	highp " << outFormat << "vec4 read_colors[4];\n"
1074		<< "} b_out;\n"
1075		<< "void main (void)\n"
1076		<< "{\n"
1077		<< "	highp int quadrant_id = int(gl_WorkGroupID.x);\n"
1078		<< "	highp " << outFormat << "vec4 result_color;\n"
1079		<< "	result_color = " << outFormat << "vec4(0);\n"
1080		<< "	if (quadrant_id == 0)\n"
1081		<< "		result_color += " << outFormat << "vec4(" << opName << "(texelBuffer, 6));\n"
1082		<< "	else if (quadrant_id == 1)\n"
1083		<< "		result_color += " << outFormat << "vec4(" << opName << "(texelBuffer, 51));\n"
1084		<< "	else if (quadrant_id == 2)\n"
1085		<< "		result_color += " << outFormat << "vec4(" << opName << "(texelBuffer, 42));\n"
1086		<< "	else\n"
1087		<< "		result_color += " << outFormat << "vec4(" << opName << "(texelBuffer, 25));\n"
1088		<< "	b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
1089		<< "}\n";
1090
1091	programCollection.glslSources.add("comp") << glu::ComputeSource(buf.str());
1092}
1093
1094} // anonymous
1095
1096bool isSupportedImageLoadStore (const tcu::TextureFormat& format)
1097{
1098	if (!image::isPackedType(mapTextureFormat(format)))
1099	{
1100		switch (format.order)
1101		{
1102			case tcu::TextureFormat::RGBA:
1103				break;
1104			default:
1105				return false;
1106		}
1107
1108		switch (format.type)
1109		{
1110			case tcu::TextureFormat::FLOAT:
1111			case tcu::TextureFormat::HALF_FLOAT:
1112
1113			case tcu::TextureFormat::UNSIGNED_INT32:
1114			case tcu::TextureFormat::UNSIGNED_INT16:
1115			case tcu::TextureFormat::UNSIGNED_INT8:
1116
1117			case tcu::TextureFormat::SIGNED_INT32:
1118			case tcu::TextureFormat::SIGNED_INT16:
1119			case tcu::TextureFormat::SIGNED_INT8:
1120
1121			case tcu::TextureFormat::UNORM_INT16:
1122			case tcu::TextureFormat::UNORM_INT8:
1123
1124			case tcu::TextureFormat::SNORM_INT16:
1125			case tcu::TextureFormat::SNORM_INT8:
1126				break;
1127
1128			default:
1129				return false;
1130		}
1131	}
1132	else
1133	{
1134		switch (mapTextureFormat(format))
1135		{
1136			case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
1137			case VK_FORMAT_A2B10G10R10_UINT_PACK32:
1138				break;
1139
1140			default:
1141				return false;
1142		}
1143	}
1144
1145	return true;
1146}
1147
1148tcu::TestCaseGroup* createBufferViewAccessTests							(tcu::TestContext&			testCtx)
1149{
1150	const char* const				bufferTexts[ALLOCATION_KIND_LAST]	=
1151	{
1152		"buffer_suballocated",
1153		"buffer_dedicated_alloc"
1154	};
1155
1156	const char* const				imageTexts[ALLOCATION_KIND_LAST]	=
1157	{
1158		"image_suballocated",
1159		"image_dedicated_alloc"
1160	};
1161
1162	de::MovePtr<tcu::TestCaseGroup>	bufferViewTests						(new tcu::TestCaseGroup(testCtx, "access"));
1163	de::MovePtr<tcu::TestCaseGroup>	bufferViewAllocationGroupTests[]	=
1164	{
1165		// BufferView Access Tests for Suballocated Objects
1166		de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "suballocation")),
1167		de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "dedicated_alloc", "BufferView Access Tests for Dedicatedly Allocated Objects"))
1168	};
1169
1170	for (deUint32 buffersAllocationNdx = 0u; buffersAllocationNdx < ALLOCATION_KIND_LAST; ++buffersAllocationNdx)
1171	for (deUint32 imageAllocationNdx = 0u; imageAllocationNdx < ALLOCATION_KIND_LAST; ++imageAllocationNdx)
1172	{
1173		const deUint32				testCaseGroupNdx					= (buffersAllocationNdx == 0u && imageAllocationNdx == 0u) ? 0u : 1u;
1174		de::MovePtr<tcu::TestCaseGroup>&
1175									currentTestsGroup					= bufferViewAllocationGroupTests[testCaseGroupNdx];
1176		{
1177			const BufferViewCaseParams	info							=
1178			{
1179				512,													// deUint32					bufferSize
1180				512,													// deUint32					bufferViewSize
1181				0,														// deUint32					elementOffset
1182				static_cast<AllocationKind>(buffersAllocationNdx),
1183				static_cast<AllocationKind>(imageAllocationNdx)
1184			};
1185			std::ostringstream		name;
1186			name << "buffer_view_memory_test_complete";
1187			if (testCaseGroupNdx != 0)
1188				name << "_with_" << bufferTexts[buffersAllocationNdx] << "_" << imageTexts[imageAllocationNdx];
1189			currentTestsGroup->addChild(new BufferViewTestCase(testCtx, name.str(), info));
1190		}
1191
1192		{
1193			const BufferViewCaseParams	info							=
1194			{
1195				4096,													// deUint32					bufferSize
1196				512,													// deUint32					bufferViewSize
1197				0,														// deUint32					elementOffset
1198				static_cast<AllocationKind>(buffersAllocationNdx),
1199				static_cast<AllocationKind>(imageAllocationNdx)
1200			};
1201			std::ostringstream		name;
1202			name << "buffer_view_memory_test_partial_offset0";
1203			if (testCaseGroupNdx != 0)
1204				name << "_with_" << bufferTexts[buffersAllocationNdx] << "_" << imageTexts[imageAllocationNdx];
1205			currentTestsGroup->addChild(new BufferViewTestCase(testCtx, name.str(), info));
1206		}
1207
1208		{
1209			const BufferViewCaseParams	info							=
1210			{
1211				4096,													// deUint32					bufferSize
1212				512,													// deUint32					bufferViewSize
1213				128,													// deUint32					elementOffset
1214				static_cast<AllocationKind>(buffersAllocationNdx),
1215				static_cast<AllocationKind>(imageAllocationNdx)
1216			};
1217			std::ostringstream		name;
1218			name << "buffer_view_memory_test_partial_offset1";
1219			if (testCaseGroupNdx != 0)
1220				name << "_with_" << bufferTexts[buffersAllocationNdx] << "_" << imageTexts[imageAllocationNdx];
1221			currentTestsGroup->addChild(new BufferViewTestCase(testCtx, name.str(), info));
1222		}
1223	}
1224
1225	for (deUint32 subgroupNdx = 0u; subgroupNdx < DE_LENGTH_OF_ARRAY(bufferViewAllocationGroupTests); ++subgroupNdx)
1226	{
1227		bufferViewTests->addChild(bufferViewAllocationGroupTests[subgroupNdx].release());
1228	}
1229
1230	VkFormat testFormats[] =
1231	{
1232		VK_FORMAT_R4G4_UNORM_PACK8,
1233		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1234		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1235		VK_FORMAT_R5G6B5_UNORM_PACK16,
1236		VK_FORMAT_B5G6R5_UNORM_PACK16,
1237		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
1238		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
1239		VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1240#ifndef CTS_USES_VULKANSC
1241		VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
1242#endif // CTS_USES_VULKANSC
1243		VK_FORMAT_R8_UNORM,
1244		VK_FORMAT_R8_SNORM,
1245		VK_FORMAT_R8_USCALED,
1246		VK_FORMAT_R8_SSCALED,
1247		VK_FORMAT_R8_UINT,
1248		VK_FORMAT_R8_SINT,
1249#ifndef CTS_USES_VULKANSC
1250		VK_FORMAT_A8_UNORM_KHR,
1251#endif // CTS_USES_VULKANSC
1252		VK_FORMAT_R8G8_UNORM,
1253		VK_FORMAT_R8G8_SNORM,
1254		VK_FORMAT_R8G8_USCALED,
1255		VK_FORMAT_R8G8_SSCALED,
1256		VK_FORMAT_R8G8_UINT,
1257		VK_FORMAT_R8G8_SINT,
1258		VK_FORMAT_R8G8B8_UNORM,
1259		VK_FORMAT_R8G8B8_SNORM,
1260		VK_FORMAT_R8G8B8_USCALED,
1261		VK_FORMAT_R8G8B8_SSCALED,
1262		VK_FORMAT_R8G8B8_UINT,
1263		VK_FORMAT_R8G8B8_SINT,
1264		VK_FORMAT_B8G8R8_UNORM,
1265		VK_FORMAT_B8G8R8_SNORM,
1266		VK_FORMAT_B8G8R8_USCALED,
1267		VK_FORMAT_B8G8R8_SSCALED,
1268		VK_FORMAT_B8G8R8_UINT,
1269		VK_FORMAT_B8G8R8_SINT,
1270		VK_FORMAT_R8G8B8A8_UNORM,
1271		VK_FORMAT_R8G8B8A8_SNORM,
1272		VK_FORMAT_R8G8B8A8_USCALED,
1273		VK_FORMAT_R8G8B8A8_SSCALED,
1274		VK_FORMAT_R8G8B8A8_UINT,
1275		VK_FORMAT_R8G8B8A8_SINT,
1276		VK_FORMAT_B8G8R8A8_UNORM,
1277		VK_FORMAT_B8G8R8A8_SNORM,
1278		VK_FORMAT_B8G8R8A8_USCALED,
1279		VK_FORMAT_B8G8R8A8_SSCALED,
1280		VK_FORMAT_B8G8R8A8_UINT,
1281		VK_FORMAT_B8G8R8A8_SINT,
1282		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1283		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1284		VK_FORMAT_A8B8G8R8_USCALED_PACK32,
1285		VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
1286		VK_FORMAT_A8B8G8R8_UINT_PACK32,
1287		VK_FORMAT_A8B8G8R8_SINT_PACK32,
1288		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1289		VK_FORMAT_A2R10G10B10_SNORM_PACK32,
1290		VK_FORMAT_A2R10G10B10_USCALED_PACK32,
1291		VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
1292		VK_FORMAT_A2R10G10B10_UINT_PACK32,
1293		VK_FORMAT_A2R10G10B10_SINT_PACK32,
1294		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1295		VK_FORMAT_A2B10G10R10_SNORM_PACK32,
1296		VK_FORMAT_A2B10G10R10_USCALED_PACK32,
1297		VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
1298		VK_FORMAT_A2B10G10R10_UINT_PACK32,
1299		VK_FORMAT_A2B10G10R10_SINT_PACK32,
1300		VK_FORMAT_R16_UNORM,
1301		VK_FORMAT_R16_SNORM,
1302		VK_FORMAT_R16_USCALED,
1303		VK_FORMAT_R16_SSCALED,
1304		VK_FORMAT_R16_UINT,
1305		VK_FORMAT_R16_SINT,
1306		VK_FORMAT_R16_SFLOAT,
1307		VK_FORMAT_R16G16_UNORM,
1308		VK_FORMAT_R16G16_SNORM,
1309		VK_FORMAT_R16G16_USCALED,
1310		VK_FORMAT_R16G16_SSCALED,
1311		VK_FORMAT_R16G16_UINT,
1312		VK_FORMAT_R16G16_SINT,
1313		VK_FORMAT_R16G16_SFLOAT,
1314		VK_FORMAT_R16G16B16_UNORM,
1315		VK_FORMAT_R16G16B16_SNORM,
1316		VK_FORMAT_R16G16B16_USCALED,
1317		VK_FORMAT_R16G16B16_SSCALED,
1318		VK_FORMAT_R16G16B16_UINT,
1319		VK_FORMAT_R16G16B16_SINT,
1320		VK_FORMAT_R16G16B16_SFLOAT,
1321		VK_FORMAT_R16G16B16A16_UNORM,
1322		VK_FORMAT_R16G16B16A16_SNORM,
1323		VK_FORMAT_R16G16B16A16_USCALED,
1324		VK_FORMAT_R16G16B16A16_SSCALED,
1325		VK_FORMAT_R16G16B16A16_UINT,
1326		VK_FORMAT_R16G16B16A16_SINT,
1327		VK_FORMAT_R16G16B16A16_SFLOAT,
1328		VK_FORMAT_R32_UINT,
1329		VK_FORMAT_R32_SINT,
1330		VK_FORMAT_R32_SFLOAT,
1331		VK_FORMAT_R32G32_UINT,
1332		VK_FORMAT_R32G32_SINT,
1333		VK_FORMAT_R32G32_SFLOAT,
1334	};
1335
1336	{
1337		const char* const					usageName[]						= { "uniform_texel_buffer", "storage_texel_buffer"};
1338		const vk::VkBufferUsageFlags		createUsage[]					= { vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT };
1339		const vk::VkBufferUsageFlags		bindUsage[]						= { vk::VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM, vk::VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM };
1340		const vk::VkFormatFeatureFlags		feature[]						= { vk::VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT, vk::VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT };
1341		const vk::VkDescriptorType			descType[]						= { vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER };
1342
1343		for (deUint32 usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(createUsage); ++usageNdx)
1344		{
1345			de::MovePtr<tcu::TestCaseGroup>	usageGroup		(new tcu::TestCaseGroup(testCtx, usageName[usageNdx], ""));
1346
1347			for (deUint32 formatIdx = 0; formatIdx < DE_LENGTH_OF_ARRAY(testFormats); formatIdx++)
1348			{
1349				const auto			skip	= strlen("VK_FORMAT_");
1350				const std::string	fmtName	= de::toLower(std::string(getFormatName(testFormats[formatIdx])).substr(skip));
1351
1352				de::MovePtr<tcu::TestCaseGroup>	formatGroup		(new tcu::TestCaseGroup(testCtx, fmtName.c_str(), ""));
1353
1354				if (createUsage[usageNdx] == VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT && !isSupportedImageLoadStore(mapVkFormat(testFormats[formatIdx])))
1355					continue;
1356
1357				const BufferViewCaseParams	info							=
1358				{
1359					512,													// deUint32					bufferSize
1360					128,													// deUint32					bufferViewSize
1361					0,														// deUint32					elementOffset
1362					ALLOCATION_KIND_SUBALLOCATION,							// AllocationKind			bufferAllocationKind
1363					ALLOCATION_KIND_SUBALLOCATION,							// AllocationKind			imageAllocationKind
1364
1365					testFormats[formatIdx],									// VkFormat					format
1366					createUsage[usageNdx],									// VkBufferUsageFlags		createUsage
1367					bindUsage[usageNdx],									// VkBufferUsageFlags		bindUsage
1368					feature[usageNdx],										// VkFormatFeatureFlags2KHR	feature
1369					descType[usageNdx],										// VkDescriptorType			descType
1370				};
1371
1372				usageGroup->addChild(new BufferViewAllFormatsTestCase(testCtx, fmtName.c_str(), info));
1373			}
1374
1375			bufferViewTests->addChild(usageGroup.release());
1376		}
1377	}
1378
1379#ifndef CTS_USES_VULKANSC
1380	de::MovePtr<tcu::TestCaseGroup> uniformStorageGroup		(new tcu::TestCaseGroup(testCtx, "uniform_storage_texel_buffer", ""));
1381	{
1382
1383		const char* const					usageName[]	= { "bind_as_uniform", "bind_as_storage" };
1384		const vk::VkBufferUsageFlags		createUsage	= vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1385		const vk::VkBufferUsageFlags		bindUsage[]	= { vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT };
1386		const vk::VkFormatFeatureFlags		feature[]	= { vk::VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT, vk::VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT };
1387		const vk::VkDescriptorType			descType[]	= { vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER };
1388
1389		for (deUint32 usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageName); ++usageNdx)
1390		{
1391			de::MovePtr<tcu::TestCaseGroup>	usageGroup		(new tcu::TestCaseGroup(testCtx, usageName[usageNdx], ""));
1392
1393			for (deUint32 formatIdx = 0; formatIdx < DE_LENGTH_OF_ARRAY(testFormats); formatIdx++)
1394			{
1395				const auto			skip	= strlen("VK_FORMAT_");
1396				const std::string	fmtName	= de::toLower(std::string(getFormatName(testFormats[formatIdx])).substr(skip));
1397
1398				de::MovePtr<tcu::TestCaseGroup>	formatGroup(new tcu::TestCaseGroup(testCtx, fmtName.c_str(), ""));
1399
1400				if (bindUsage[usageNdx] == VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT && !isSupportedImageLoadStore(mapVkFormat(testFormats[formatIdx])))
1401					continue;
1402
1403				const BufferViewCaseParams	info =
1404				{
1405					512,													// deUint32					bufferSize
1406					128,													// deUint32					bufferViewSize
1407					0,														// deUint32					elementOffset
1408					ALLOCATION_KIND_SUBALLOCATION,							// AllocationKind			bufferAllocationKind
1409					ALLOCATION_KIND_SUBALLOCATION,							// AllocationKind			imageAllocationKind
1410
1411					testFormats[formatIdx],									// VkFormat					format
1412					createUsage,											// VkBufferUsageFlags		createUsage
1413					bindUsage[usageNdx],									// VkBufferUsageFlags		bindUsage
1414					feature[usageNdx],										// VkFormatFeatureFlags2KHR	feature
1415					descType[usageNdx],										// VkDescriptorType			descType
1416				};
1417
1418				usageGroup->addChild(new BufferViewAllFormatsTestCase(testCtx, fmtName.c_str(), info));
1419			}
1420
1421			uniformStorageGroup->addChild(usageGroup.release());
1422		}
1423	}
1424
1425	bufferViewTests->addChild(uniformStorageGroup.release());
1426#endif
1427
1428	return bufferViewTests.release();
1429}
1430
1431} // api
1432} // vkt
1433