1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Geometry Basic Class
23 *//*--------------------------------------------------------------------*/
24
25#include "vktGeometryBasicClass.hpp"
26
27#include "vkDefs.hpp"
28#include "vktTestCase.hpp"
29#include "vktTestCaseUtil.hpp"
30#include "vkBarrierUtil.hpp"
31#include "vkImageUtil.hpp"
32#include "vkPrograms.hpp"
33#include "vkBuilderUtil.hpp"
34#include "vkRefUtil.hpp"
35#include "vkQueryUtil.hpp"
36#include "vkMemUtil.hpp"
37#include "vkCmdUtil.hpp"
38#include "vkObjUtil.hpp"
39#include "vkBufferWithMemory.hpp"
40#include "vkImageWithMemory.hpp"
41
42#include <string>
43
44namespace vkt
45{
46namespace geometry
47{
48using namespace vk;
49using tcu::IVec2;
50using tcu::Vec4;
51using tcu::TestStatus;
52using tcu::TestContext;
53using tcu::TestCaseGroup;
54using de::MovePtr;
55using std::string;
56using std::vector;
57using std::size_t;
58
59static const int TEST_CANVAS_SIZE = 256;
60
61GeometryExpanderRenderTestInstance::GeometryExpanderRenderTestInstance (Context&					context,
62																		const VkPrimitiveTopology	primitiveType,
63																		const char*					name)
64	: TestInstance		(context)
65	, m_primitiveType	(primitiveType)
66	, m_name			(name)
67	, m_numDrawVertices	(0)
68{
69}
70
71tcu::TestStatus GeometryExpanderRenderTestInstance::iterate (void)
72{
73	const DeviceInterface&			vk						= m_context.getDeviceInterface();
74	const VkDevice					device					= m_context.getDevice();
75	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
76	const VkQueue					queue					= m_context.getUniversalQueue();
77	Allocator&						memAlloc				= m_context.getDefaultAllocator();
78	const IVec2						resolution				= IVec2(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
79	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
80	const ImageWithMemory			colorAttachmentImage	(
81																vk,
82																device,
83																memAlloc,
84																makeImageCreateInfo(resolution, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
85																MemoryRequirement::Any
86															);
87	const Unique<VkRenderPass>		renderPass				(makeRenderPass(vk, device, colorFormat));
88
89	const Move<VkPipelineLayout>	pipelineLayout			(createPipelineLayout(vk, device));
90	const VkImageSubresourceRange	colorSubRange			= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
91	const Unique<VkImageView>		colorAttachmentView		(makeImageView(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubRange));
92	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer(vk, device, *renderPass, *colorAttachmentView, resolution.x(), resolution.y(), 1u));
93	const Unique<VkCommandPool>		cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
94	const Unique<VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
95
96	const VkDeviceSize				vertexDataSizeBytes		= sizeInBytes(m_vertexPosData) + sizeInBytes(m_vertexAttrData);
97	const deUint32					vertexPositionsOffset	= 0u;
98	const deUint32					vertexAtrrOffset		= static_cast<deUint32>(sizeof(Vec4));
99	const string					geometryShaderName		= (m_context.getBinaryCollection().contains("geometry_pointsize") && checkPointSize (m_context.getInstanceInterface(), m_context.getPhysicalDevice()))?
100																"geometry_pointsize" : "geometry";
101
102	const Unique<VkPipeline>		pipeline				(GraphicsPipelineBuilder()
103																.setRenderSize			(resolution)
104																.setShader				(vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vertex"), DE_NULL)
105																.setShader				(vk, device, VK_SHADER_STAGE_GEOMETRY_BIT, m_context.getBinaryCollection().get(geometryShaderName), DE_NULL)
106																.setShader				(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("fragment"), DE_NULL)
107																.addVertexBinding		(makeVertexInputBindingDescription(0u, 2u*vertexAtrrOffset, VK_VERTEX_INPUT_RATE_VERTEX))
108																.addVertexAttribute		(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexPositionsOffset))
109																.addVertexAttribute		(makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexAtrrOffset))
110																.setPrimitiveTopology	(m_primitiveType)
111																.build					(vk, device, *pipelineLayout, *renderPass));
112
113	const VkDeviceSize				colorBufferSizeBytes	= resolution.x()*resolution.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
114	const BufferWithMemory			colorBuffer				(vk, device, memAlloc, makeBufferCreateInfo(colorBufferSizeBytes,
115																VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
116	const BufferWithMemory			vertexBuffer			(vk, device, memAlloc, makeBufferCreateInfo(vertexDataSizeBytes,
117																VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ), MemoryRequirement::HostVisible);
118	{
119		const Allocation& alloc = vertexBuffer.getAllocation();
120		struct DataVec4
121		{
122			Vec4 pos;
123			Vec4 color;
124		};
125
126		DataVec4* const pData = static_cast<DataVec4*>(alloc.getHostPtr());
127		for(int ndx = 0; ndx < m_numDrawVertices; ++ndx)
128		{
129			pData[ndx].pos = m_vertexPosData[ndx];
130			pData[ndx].color = m_vertexAttrData[ndx];
131		}
132		flushAlloc(vk, device, alloc);
133		// No barrier needed, flushed memory is automatically visible
134	}
135
136	// Draw commands
137	beginCommandBuffer(vk, *cmdBuffer);
138
139	// Change color attachment image layout
140	{
141		const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
142				(VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
143				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
144				*colorAttachmentImage, colorSubRange);
145
146		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
147						0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
148	}
149
150	// Begin render pass
151	{
152		const VkRect2D renderArea = {
153				makeOffset2D(0, 0),
154				makeExtent2D(resolution.x(), resolution.y()),
155			};
156			const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
157			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
158	}
159
160	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
161	{
162		const VkBuffer buffers[] = { vertexBuffer.get()};
163		const VkDeviceSize offsets[] = { vertexPositionsOffset };
164		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(buffers), buffers, offsets);
165	}
166
167	bindDescriptorSets(vk, device, memAlloc, *cmdBuffer, *pipelineLayout);
168
169	drawCommand (*cmdBuffer);
170	endRenderPass(vk, *cmdBuffer);
171
172	// Copy render result to a host-visible buffer
173	copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, resolution);
174
175	endCommandBuffer(vk, *cmdBuffer);
176	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
177
178	{
179		// Log the result image.
180		const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
181		invalidateAlloc(vk, device, colorBufferAlloc);
182		const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), resolution.x(), resolution.y(), 1, colorBufferAlloc.getHostPtr());
183
184		if (!compareWithFileImage(m_context, imagePixelAccess, m_name))
185			return TestStatus::fail("Fail");
186	}
187
188	return TestStatus::pass("Pass");
189}
190
191Move<VkPipelineLayout> GeometryExpanderRenderTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device)
192{
193	return makePipelineLayout(vk, device);
194}
195
196void GeometryExpanderRenderTestInstance::drawCommand (const VkCommandBuffer& cmdBuffer)
197{
198	const DeviceInterface& vk = m_context.getDeviceInterface();
199	vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numDrawVertices), 1u, 0u, 0u);
200}
201
202} // geometry
203} // vkt
204