1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 Google LLC
7  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Android Hardware Buffer Draw Tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktDrawAhbTests.hpp"
27 
28 #include "vktDrawBaseClass.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vktTestGroupUtil.hpp"
33 
34 #include "../util/vktExternalMemoryUtil.hpp"
35 
36 #include "deDefs.h"
37 #include "deRandom.hpp"
38 
39 #include "tcuTestCase.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuVectorUtil.hpp"
43 #include "tcuTestLog.hpp"
44 
45 #include "rrRenderer.hpp"
46 
47 #include <string>
48 
49 using namespace vkt::ExternalMemoryUtil;
50 using namespace vk;
51 using std::vector;
52 
53 namespace vkt
54 {
55 namespace Draw
56 {
57 namespace
58 {
59 
60 const deUint32 SEED = 0xc2a39fu;
61 
62 struct DrawParams
63 {
DrawParamsvkt::Draw::__anond741a9fd0111::DrawParams64 	DrawParams (deUint32 numVertices, deUint32 numLayers)
65 	: m_numVertices(numVertices), m_numLayers(numLayers) {}
66 
67 	deUint32					m_numVertices;
68 	deUint32					m_numLayers;
69 	vector<PositionColorVertex>	m_vertices;
70 };
71 
72 // Reference renderer shaders
73 class PassthruVertShader : public rr::VertexShader
74 {
75 public:
PassthruVertShader(void)76 	PassthruVertShader (void)
77 	: rr::VertexShader (2, 1)
78 	{
79 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
80 		m_inputs[1].type	= rr::GENERICVECTYPE_FLOAT;
81 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
82 	}
83 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const84 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
85 	{
86 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
87 		{
88 			packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
89 																	 packets[packetNdx]->instanceNdx,
90 																	 packets[packetNdx]->vertexNdx);
91 
92 			tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1],
93 														packets[packetNdx]->instanceNdx,
94 														packets[packetNdx]->vertexNdx);
95 
96 			packets[packetNdx]->outputs[0] = color;
97 		}
98 	}
99 };
100 
101 class PassthruFragShader : public rr::FragmentShader
102 {
103 public:
PassthruFragShader(void)104 	PassthruFragShader (void)
105 		: rr::FragmentShader(1, 1)
106 	{
107 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
108 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
109 	}
110 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const111 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
112 	{
113 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
114 		{
115 			rr::FragmentPacket& packet = packets[packetNdx];
116 			for (deUint32 fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
117 			{
118 				tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
119 				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
120 			}
121 		}
122 	}
123 };
124 
125 class AhbTestInstance : public TestInstance
126 {
127 public:
128 					AhbTestInstance		(Context& context, DrawParams data);
129 					~AhbTestInstance	(void);
130 
131 	tcu::TestStatus	iterate				(void);
132 
133 private:
134 	void			generateDrawData	(void);
135 	void			generateRefImage	(const tcu::PixelBufferAccess& access, const vector<tcu::Vec4>& vertices, const vector<tcu::Vec4>& colors) const;
136 
137 	DrawParams							m_data;
138 
139 	enum
140 	{
141 		WIDTH = 256,
142 		HEIGHT = 256
143 	};
144 };
145 
AhbTestInstance(Context & context,DrawParams data)146 AhbTestInstance::AhbTestInstance (Context& context, DrawParams data)
147 	: vkt::TestInstance			(context)
148 	, m_data					(data)
149 {
150 	generateDrawData();
151 }
152 
~AhbTestInstance(void)153 AhbTestInstance::~AhbTestInstance (void)
154 {
155 }
156 
generateRefImage(const tcu::PixelBufferAccess & access,const vector<tcu::Vec4> & vertices,const vector<tcu::Vec4> & colors) const157 void AhbTestInstance::generateRefImage (const tcu::PixelBufferAccess& access, const vector<tcu::Vec4>& vertices, const vector<tcu::Vec4>& colors) const
158 {
159 	const PassthruVertShader				vertShader;
160 	const PassthruFragShader				fragShader;
161 	const rr::Program						program			(&vertShader, &fragShader);
162 	const rr::MultisamplePixelBufferAccess	colorBuffer		= rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(access);
163 	const rr::RenderTarget					renderTarget	(colorBuffer);
164 	const rr::RenderState					renderState		((rr::ViewportState(colorBuffer)), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
165 	const rr::Renderer						renderer;
166 
167 	const rr::VertexAttrib	vertexAttribs[] =
168 	{
169 		rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vertices[0]),
170 		rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0])
171 	};
172 
173 	renderer.draw(rr::DrawCommand(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs),
174 								  &vertexAttribs[0], rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, (deUint32)vertices.size(), 0)));
175 }
176 
177 class AhbTestCase : public TestCase
178 {
179 	public:
180 									AhbTestCase			(tcu::TestContext& context, const char* name, const char* desc, const DrawParams data);
181 									~AhbTestCase		(void);
182 	virtual	void					initPrograms		(SourceCollections& programCollection) const;
183 	virtual void					initShaderSources	(void);
184 	virtual void					checkSupport		(Context& context) const;
185 	virtual TestInstance*			createInstance		(Context& context) const;
186 
187 private:
188 	DrawParams											m_data;
189 	std::string											m_vertShaderSource;
190 	std::string											m_fragShaderSource;
191 };
192 
AhbTestCase(tcu::TestContext & context,const char * name,const char * desc,const DrawParams data)193 AhbTestCase::AhbTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data)
194 	: vkt::TestCase	(context, name, desc)
195 	, m_data		(data)
196 {
197 	initShaderSources();
198 }
199 
~AhbTestCase(void)200 AhbTestCase::~AhbTestCase	(void)
201 {
202 }
203 
initPrograms(SourceCollections & programCollection) const204 void AhbTestCase::initPrograms (SourceCollections& programCollection) const
205 {
206 	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
207 	programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
208 }
209 
checkSupport(Context & context) const210 void AhbTestCase::checkSupport (Context& context) const
211 {
212 	const InstanceInterface&				vki				= context.getInstanceInterface();
213 	vk::VkPhysicalDevice					physicalDevice	= context.getPhysicalDevice();
214 	const vk::VkPhysicalDeviceProperties	properties		= vk::getPhysicalDeviceProperties(vki, physicalDevice);
215 
216 	// Each layer is exposed as its own color attachment.
217 	if (m_data.m_numLayers > properties.limits.maxColorAttachments)
218 		TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
219 }
220 
initShaderSources(void)221 void AhbTestCase::initShaderSources (void)
222 {
223 	std::stringstream vertShader;
224 	vertShader	<< "#version 430\n"
225 				<< "layout(location = 0) in vec4 in_position;\n"
226 				<< "layout(location = 1) in vec4 in_color;\n"
227 				<< "layout(location = 0) out vec4 out_color;\n"
228 
229 				<< "void main() {\n"
230 				<< "    gl_Position  = in_position;\n"
231 				<< "    out_color    = in_color;\n"
232 				<< "}\n";
233 
234 	m_vertShaderSource = vertShader.str();
235 
236 	std::stringstream fragShader;
237 	fragShader	<< "#version 430\n"
238 				<< "layout(location = 0) in vec4 in_color;\n"
239 				<< "layout(location = 0) out vec4 out_color;\n"
240 
241 				<< "void main()\n"
242 				<< "{\n"
243 				<< "    out_color = in_color;\n"
244 				<< "}\n";
245 
246 	m_fragShaderSource = fragShader.str();
247 }
248 
createInstance(Context & context) const249 TestInstance* AhbTestCase::createInstance (Context& context) const
250 {
251 	return new AhbTestInstance(context, m_data);
252 }
253 
generateDrawData(void)254 void AhbTestInstance::generateDrawData (void)
255 {
256 	de::Random rnd (SEED ^ m_data.m_numLayers ^ m_data.m_numVertices);
257 
258 	for (deUint32 i = 0; i < m_data.m_numVertices; i++)
259 	{
260 		const float f0 = rnd.getFloat(-1.0f, 1.0f);
261 		const float f1 = rnd.getFloat(-1.0f, 1.0f);
262 
263 		m_data.m_vertices.push_back(PositionColorVertex(
264 			tcu::Vec4(f0, f1, 1.0f, 1.0f),	// Coord
265 			tcu::randomVec4(rnd)));			// Color
266 	}
267 }
268 
iterate(void)269 tcu::TestStatus AhbTestInstance::iterate (void)
270 {
271 	const DeviceInterface&						vk						= m_context.getDeviceInterface();
272 	const VkFormat								colorAttachmentFormat	= VK_FORMAT_R8G8B8A8_UNORM;
273 	tcu::TestLog								&log					= m_context.getTestContext().getLog();
274 	const VkQueue								queue					= m_context.getUniversalQueue();
275 	const VkDevice								device					= m_context.getDevice();
276 	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
277 	const PipelineLayoutCreateInfo				pipelineLayoutCreateInfo;
278 	const Unique<VkPipelineLayout>				pipelineLayout			(createPipelineLayout(vk, device, &pipelineLayoutCreateInfo));
279 	vector<Move<VkBuffer>>						resultBuffers;
280 	vector<de::MovePtr<Allocation>>				resultBufferAllocations;
281 
282 	for (deUint32 i = 0u; i < m_data.m_numLayers; i++)
283 	{
284 		const VkBufferUsageFlags	bufferUsage	(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
285 		const VkDeviceSize			pixelSize	= mapVkFormat(colorAttachmentFormat).getPixelSize();
286 		const VkBufferCreateInfo	createInfo	=
287 		{
288 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType
289 			DE_NULL,								// const void*			pNext
290 			0u,										// VkBufferCreateFlags	flags
291 			WIDTH * HEIGHT * pixelSize,				// VkDeviceSize			size
292 			bufferUsage,							// VkBufferUsageFlags	usage
293 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode
294 			0u,										// uint32_t				queueFamilyIndexCount
295 			DE_NULL									// const uint32_t*		pQueueFamilyIndices
296 		};
297 
298 		resultBuffers.push_back(createBuffer(vk, device, &createInfo));
299 		resultBufferAllocations.push_back(m_context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, device, *resultBuffers.back()), MemoryRequirement::HostVisible));
300 		VK_CHECK(vk.bindBufferMemory(device, *resultBuffers.back(), resultBufferAllocations.back()->getMemory(), resultBufferAllocations.back()->getOffset()));
301 	}
302 
303 	const VkExtent3D							targetImageExtent		= { WIDTH, HEIGHT, 1 };
304 	const ImageCreateInfo						targetImageCreateInfo	(VK_IMAGE_TYPE_2D, colorAttachmentFormat, targetImageExtent, 1, m_data.m_numLayers, VK_SAMPLE_COUNT_1_BIT,
305 																	 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
306 
307 	// Enable this to use non-AHB images for color output.
308 #if 0
309 	const Unique<VkImage>						colorTargetImage		(createImage(vk, device, &targetImageCreateInfo, DE_NULL));
310 	de::MovePtr<Allocation>						m_colorImageAllocation	= m_context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, device, *colorTargetImage), MemoryRequirement::Any);
311 	VK_CHECK(vk.bindImageMemory(device, *colorTargetImage, m_colorImageAllocation->getMemory(), m_colorImageAllocation->getOffset()));
312 #else
313 	AndroidHardwareBufferExternalApi*			ahbApi					= AndroidHardwareBufferExternalApi::getInstance();
314 
315 	if (!ahbApi)
316 		TCU_THROW(NotSupportedError, "Android Hardware Buffer not supported");
317 
318 	m_context.requireDeviceFunctionality("VK_ANDROID_external_memory_android_hardware_buffer");
319 
320 	deUint64									requiredAhbUsage		= ahbApi->vkUsageToAhbUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
321 
322 	pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(WIDTH, HEIGHT, targetImageCreateInfo.arrayLayers, ahbApi->vkFormatToAhbFormat(colorAttachmentFormat), requiredAhbUsage);
323 
324 	if (ahb.internal == DE_NULL)
325 		TCU_THROW(NotSupportedError, "Required number of layers for Android Hardware Buffer not supported");
326 
327 	NativeHandle								nativeHandle(ahb);
328 	const Unique<VkImage>						colorTargetImage	(createExternalImage(vk, device, queueFamilyIndex, VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
329 																	 colorAttachmentFormat, WIDTH, HEIGHT, VK_IMAGE_TILING_OPTIMAL, 0u,
330 																	 targetImageCreateInfo.usage, targetImageCreateInfo.mipLevels, targetImageCreateInfo.arrayLayers));
331 
332 	deUint32									ahbFormat			= 0;
333 	ahbApi->describe(nativeHandle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, DE_NULL, DE_NULL);
334 
335 	VkAndroidHardwareBufferPropertiesANDROID	ahbProperties		=
336 	{
337 		VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,	// VkStructureType    sType
338 		DE_NULL,														// void*              pNext
339 		0u,																// VkDeviceSize       allocationSize
340 		0u																// uint32_t           memoryTypeBits
341 	};
342 
343 	vk.getAndroidHardwareBufferPropertiesANDROID(device, nativeHandle.getAndroidHardwareBuffer(), &ahbProperties);
344 
345 	const VkImportAndroidHardwareBufferInfoANDROID	importInfo		=
346 	{
347 		VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,	// VkStructureType            sType
348 		DE_NULL,														// const void*                pNext
349 		nativeHandle.getAndroidHardwareBuffer()							// struct AHardwareBuffer*    buffer
350 	};
351 
352 	const VkMemoryDedicatedAllocateInfo			dedicatedInfo		=
353 	{
354 		VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,	// VkStructureType    sType
355 		&importInfo,											// const void*        pNext
356 		*colorTargetImage,										// VkImage            image
357 		DE_NULL,												// VkBuffer           buffer
358 	};
359 
360 	const VkMemoryAllocateInfo					allocateInfo		=
361 	{
362 			VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,			// VkStructureType    sType
363 			(const void*)&dedicatedInfo,					// const void*        pNext
364 			ahbProperties.allocationSize,					// VkDeviceSize       allocationSize
365 			chooseMemoryType(ahbProperties.memoryTypeBits)	// uint32_t           memoryTypeIndex
366 	};
367 
368 	const Unique<VkDeviceMemory>				colorImageMemory	(allocateMemory(vk, device, &allocateInfo));
369 	VK_CHECK(vk.bindImageMemory(device, *colorTargetImage, *colorImageMemory, 0u));
370 #endif
371 
372 	vector<Move<VkImageView>>					imageViews;
373 	vector<VkImageView>							colorAttachments;
374 	RenderPassCreateInfo						renderPassCreateInfo;
375 
376 	for (deUint32 i = 0u; i < m_data.m_numLayers; i++)
377 	{
378 		const VkImageSubresourceRange	subresourceRange	=
379 		{
380 			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags    aspectMask
381 			0u,							// uint32_t              baseMipLevel
382 			1u,							// uint32_t              levelCount
383 			i,							// uint32_t              baseArrayLayer
384 			1u,							// uint32_t              layerCount
385 		};
386 
387 		const VkImageViewCreateInfo		imageViewCreateInfo	=
388 		{
389 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType            sType
390 			DE_NULL,									// const void*                pNext
391 			0u,											// VkImageViewCreateFlags     flags
392 			*colorTargetImage,							// VkImage                    image
393 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType            viewType
394 			colorAttachmentFormat,						// VkFormat                   format
395 			ComponentMapping(),							// VkComponentMapping         components
396 			subresourceRange							// VkImageSubresourceRange    subresourceRange
397 		};
398 
399 		imageViews.push_back(createImageView(vk, device, &imageViewCreateInfo));
400 		colorAttachments.push_back(*imageViews.back());
401 
402 		renderPassCreateInfo.addAttachment(AttachmentDescription(colorAttachmentFormat,
403 																 VK_SAMPLE_COUNT_1_BIT,
404 																 VK_ATTACHMENT_LOAD_OP_CLEAR,
405 																 VK_ATTACHMENT_STORE_OP_STORE,
406 																 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
407 																 VK_ATTACHMENT_STORE_OP_STORE,
408 																 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
409 																 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
410 
411 
412 		const VkAttachmentReference		colorAttachmentReference	=
413 		{
414 			i,
415 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
416 		};
417 
418 		renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
419 														   0,
420 														   0,
421 														   DE_NULL,
422 														   1u,
423 														   &colorAttachmentReference,
424 														   DE_NULL,
425 														   AttachmentReference(),
426 														   0,
427 														   DE_NULL));
428 	}
429 
430 	Unique<VkRenderPass>				renderPass					(createRenderPass(vk, device, &renderPassCreateInfo));
431 
432 	const FramebufferCreateInfo			framebufferCreateInfo		(*renderPass, colorAttachments, WIDTH, HEIGHT, 1);
433 	Unique<VkFramebuffer>				framebuffer					(createFramebuffer(vk, device, &framebufferCreateInfo));
434 
435 	const VkVertexInputBindingDescription vertexInputBindingDescription =
436 	{
437 		0,									// uint32_t             binding
438 		(deUint32)sizeof(tcu::Vec4) * 2,	// uint32_t             stride
439 		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate    inputRate
440 	};
441 
442 	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
443 	{
444 
445 		{
446 			0u,								// uint32_t    location
447 			0u,								// uint32_t    binding
448 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat    format
449 			0u								// uint32_t    offset
450 		},
451 		{
452 			1u,								// uint32_t    location
453 			0u,								// uint32_t    binding
454 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat    format
455 			(deUint32)(sizeof(float)* 4),	// uint32_t    offset
456 		}
457 	};
458 
459 	PipelineCreateInfo::VertexInputState	vertexInputState		= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
460 	const VkDeviceSize						dataSize				= m_data.m_vertices.size() * sizeof(PositionColorVertex);
461 	de::SharedPtr<Buffer>					vertexBuffer			= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize,
462 																	  VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
463 	deUint8*								ptr						= reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
464 
465 	deMemcpy(ptr, &(m_data.m_vertices[0]), static_cast<size_t>(dataSize));
466 	flushAlloc(vk, device, vertexBuffer->getBoundMemory());
467 
468 	const CmdPoolCreateInfo					cmdPoolCreateInfo		(queueFamilyIndex);
469 	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, device, &cmdPoolCreateInfo));
470 	const Unique<VkCommandBuffer>			cmdBuffer				(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
471 	const Unique<VkShaderModule>			vs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
472 	const Unique<VkShaderModule>			fs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
473 	VkViewport								viewport				= makeViewport(WIDTH, HEIGHT);
474 	VkRect2D								scissor					= makeRect2D(WIDTH, HEIGHT);
475 	vector<Move<VkPipeline>>				pipelines;
476 
477 	PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
478 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
479 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
480 	pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
481 	pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
482 	PipelineCreateInfo::ColorBlendState::Attachment	attachment;
483 	pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1u, &attachment));
484 	pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
485 	pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
486 	pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
487 	pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
488 
489 	for (deUint32 i = 0; i < m_data.m_numLayers; i++)
490 	{
491 		pipelineCreateInfo.subpass = i;
492 		pipelines.push_back(createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo));
493 	}
494 
495 	beginCommandBuffer(vk, *cmdBuffer, 0u);
496 
497 	const VkImageMemoryBarrier				initialTransition		=
498 	{
499 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType	sType
500 		DE_NULL,									// const void*		pNext
501 		0u,											// VkAccessFlags	srcAccessMask
502 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags	dstAccessMask
503 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout	oldLayout
504 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	newLayout
505 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex
506 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			destQueueFamilyIndex
507 		*colorTargetImage,							// VkImage			image
508 		makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, m_data.m_numLayers)	// VkImageSubresourceRange	subresourceRange
509 	};
510 
511 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL,
512 						  0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &initialTransition);
513 
514 	const VkRect2D							renderArea				= makeRect2D(WIDTH, HEIGHT);
515 
516 	vector<VkClearValue>					clearColors				(m_data.m_numLayers, makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
517 
518 	const VkRenderPassBeginInfo				renderPassBeginInfo		=
519 	{
520 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType         sType
521 		DE_NULL,									// const void*             pNext
522 		*renderPass,								// VkRenderPass            renderPass
523 		*framebuffer,								// VkFramebuffer           framebuffer
524 		renderArea,									// VkRect2D                renderArea
525 		(deUint32)clearColors.size(),				// deUint32                clearValueCount
526 		clearColors.data(),							// const VkClearValue*     pClearValues
527 	};
528 
529 	vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
530 
531 	const VkDeviceSize						vertexBufferOffset		= 0;
532 	const VkBuffer							vertexBufferObj			= vertexBuffer->object();
533 
534 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBufferObj, &vertexBufferOffset);
535 	for (deUint32 i = 0; i < m_data.m_numLayers; i++)
536 	{
537 		if (i != 0)
538 			vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
539 
540 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines[i]);
541 		vk.cmdDraw(*cmdBuffer, 9u, 1u, i * 9u, 0u);
542 	}
543 
544 	endRenderPass(vk, *cmdBuffer);
545 
546 	const VkImageMemoryBarrier				imageBarrier			=
547 	{
548 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType
549 		DE_NULL,									// const void*				pNext
550 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask
551 		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask
552 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout
553 		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout
554 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex
555 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex
556 		*colorTargetImage,							// VkImage					image
557 		makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, m_data.m_numLayers)	// VkImageSubresourceRange	subresourceRange;
558 	};
559 
560 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
561 						  0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
562 
563 	for (deUint32 i = 0; i < m_data.m_numLayers; i++)
564 	{
565 		const VkImageSubresourceLayers	subresource	=
566 		{
567 			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
568 			0u,							// deUint32				mipLevel
569 			i,							// deUint32				baseArrayLayer
570 			1u							// deUint32				layerCount
571 		};
572 
573 		const VkBufferImageCopy			region		=
574 		{
575 			0ull,							// VkDeviceSize					bufferOffset
576 			0u,								// deUint32						bufferRowLength
577 			0u,								// deUint32						bufferImageHeight
578 			subresource,					// VkImageSubresourceLayers		imageSubresource
579 			makeOffset3D(0, 0, 0),			// VkOffset3D					imageOffset
580 			makeExtent3D(WIDTH, HEIGHT, 1u)	// VkExtent3D					imageExtent
581 		};
582 
583 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorTargetImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resultBuffers[i], 1u, &region);
584 
585 		const VkBufferMemoryBarrier	bufferBarrier =
586 		{
587 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType
588 			DE_NULL,									// const void*		pNext
589 			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask
590 			VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask
591 			VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex
592 			VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex
593 			*resultBuffers[i],							// VkBuffer			buffer
594 			0ull,										// VkDeviceSize		offset
595 			VK_WHOLE_SIZE								// VkDeviceSize		size
596 		};
597 
598 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
599 							  0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
600 	}
601 
602 	endCommandBuffer(vk, *cmdBuffer);
603 
604 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
605 
606 	qpTestResult res = QP_TEST_RESULT_PASS;
607 
608 	for (deUint32 i = 0; i < m_data.m_numLayers; i++)
609 	{
610 		invalidateMappedMemoryRange(vk, m_context.getDevice(), resultBufferAllocations[i]->getMemory(),
611 									resultBufferAllocations[i]->getOffset(), VK_WHOLE_SIZE);
612 
613 		tcu::TextureLevel					refImage(mapVkFormat(colorAttachmentFormat), WIDTH, HEIGHT);
614 		tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
615 
616 		vector<tcu::Vec4>					vertices;
617 		vector<tcu::Vec4>					colors;
618 
619 		for (int v = 0; v < 9; v++)
620 		{
621 			int idx = i * 9 + v;
622 			vertices.push_back(m_data.m_vertices[idx].position);
623 			colors.push_back(m_data.m_vertices[idx].color);
624 		}
625 
626 		generateRefImage(refImage.getAccess(), vertices, colors);
627 
628 		const tcu::TextureFormat			format			(mapVkFormat(colorAttachmentFormat));
629 		const void *const					ptrResult		(resultBufferAllocations[i]->getHostPtr());
630 		const tcu::ConstPixelBufferAccess	renderedFrame	(format, WIDTH, HEIGHT, 1, ptrResult);
631 
632 		if (!tcu::fuzzyCompare(log, "Result", "Image comparison result", refImage.getAccess(), renderedFrame, 0.053f, tcu::COMPARE_LOG_RESULT))
633 			res = QP_TEST_RESULT_FAIL;
634 	}
635 
636 	return tcu::TestStatus(res, qpGetTestResultName(res));
637 }
638 
createAhbDrawTests(tcu::TestCaseGroup * testGroup)639 void createAhbDrawTests (tcu::TestCaseGroup* testGroup)
640 {
641 	testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list", "Draw triangle list to a single layer color buffer",
642 									 DrawParams(9u, 1u)));
643 
644 	testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_3", "Draw triangle list to a color buffer with three layers",
645 										DrawParams(9u * 3u, 3u)));
646 
647 	testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_5", "Draw triangle list to a color buffer with five layers",
648 										DrawParams(9u * 5u, 5u)));
649 
650 	testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_8", "Draw triangle list to a color buffer with eight layers",
651 										DrawParams(9u * 8u, 8u)));
652 
653 }
654 
655 }	// anonymous
656 
createAhbTests(tcu::TestContext & testCtx)657 tcu::TestCaseGroup*	createAhbTests (tcu::TestContext& testCtx)
658 {
659 	return createTestGroup(testCtx, "ahb", "Draw tests using Android Hardware Buffer", createAhbDrawTests);
660 }
661 
662 }	// DrawTests
663 }	// vkt
664