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