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 
40 #include <string>
41 
42 namespace vkt
43 {
44 namespace geometry
45 {
46 using namespace vk;
47 using tcu::IVec2;
48 using tcu::Vec4;
49 using tcu::TestStatus;
50 using tcu::TestContext;
51 using tcu::TestCaseGroup;
52 using de::MovePtr;
53 using std::string;
54 using std::vector;
55 using std::size_t;
56 
57 static const int TEST_CANVAS_SIZE = 256;
58 
GeometryExpanderRenderTestInstance(Context & context,const VkPrimitiveTopology primitiveType,const char * name)59 GeometryExpanderRenderTestInstance::GeometryExpanderRenderTestInstance (Context&					context,
60 																		const VkPrimitiveTopology	primitiveType,
61 																		const char*					name)
62 	: TestInstance		(context)
63 	, m_primitiveType	(primitiveType)
64 	, m_name			(name)
65 {
66 	checkGeometryShaderSupport(context.getInstanceInterface(), context.getPhysicalDevice());
67 }
68 
iterate(void)69 tcu::TestStatus GeometryExpanderRenderTestInstance::iterate (void)
70 {
71 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
72 	const VkDevice					device					= m_context.getDevice();
73 	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
74 	const VkQueue					queue					= m_context.getUniversalQueue();
75 	Allocator&						memAlloc				= m_context.getDefaultAllocator();
76 	const IVec2						resolution				= IVec2(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
77 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
78 	const Image						colorAttachmentImage	(
79 																vk,
80 																device,
81 																memAlloc,
82 																makeImageCreateInfo(resolution, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
83 																MemoryRequirement::Any
84 															);
85 	const Unique<VkRenderPass>		renderPass				(makeRenderPass(vk, device, colorFormat));
86 
87 	const Move<VkPipelineLayout>	pipelineLayout			(createPipelineLayout(vk, device));
88 	const VkImageSubresourceRange	colorSubRange			= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
89 	const Unique<VkImageView>		colorAttachmentView		(makeImageView(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubRange));
90 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer(vk, device, *renderPass, *colorAttachmentView, resolution.x(), resolution.y(), 1u));
91 	const Unique<VkCommandPool>		cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
92 	const Unique<VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
93 
94 	const VkDeviceSize				vertexDataSizeBytes		= sizeInBytes(m_vertexPosData) + sizeInBytes(m_vertexAttrData);
95 	const deUint32					vertexPositionsOffset	= 0u;
96 	const deUint32					vertexAtrrOffset		= static_cast<deUint32>(sizeof(Vec4));
97 	const string					geometryShaderName		= (m_context.getBinaryCollection().contains("geometry_pointsize") && checkPointSize (m_context.getInstanceInterface(), m_context.getPhysicalDevice()))?
98 																"geometry_pointsize" : "geometry";
99 
100 	const Unique<VkPipeline>		pipeline				(GraphicsPipelineBuilder()
101 																.setRenderSize			(resolution)
102 																.setShader				(vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vertex"), DE_NULL)
103 																.setShader				(vk, device, VK_SHADER_STAGE_GEOMETRY_BIT, m_context.getBinaryCollection().get(geometryShaderName), DE_NULL)
104 																.setShader				(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("fragment"), DE_NULL)
105 																.addVertexBinding		(makeVertexInputBindingDescription(0u, 2u*vertexAtrrOffset, VK_VERTEX_INPUT_RATE_VERTEX))
106 																.addVertexAttribute		(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexPositionsOffset))
107 																.addVertexAttribute		(makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexAtrrOffset))
108 																.setPrimitiveTopology	(m_primitiveType)
109 																.build					(vk, device, *pipelineLayout, *renderPass));
110 
111 	const VkDeviceSize				colorBufferSizeBytes	= resolution.x()*resolution.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
112 	const Buffer					colorBuffer				(vk, device, memAlloc, makeBufferCreateInfo(colorBufferSizeBytes,
113 																VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
114 	const Buffer					vertexBuffer			(vk, device, memAlloc, makeBufferCreateInfo(vertexDataSizeBytes,
115 																VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ), MemoryRequirement::HostVisible);
116 	{
117 		const Allocation& alloc = vertexBuffer.getAllocation();
118 		struct DataVec4
119 		{
120 			Vec4 pos;
121 			Vec4 color;
122 		};
123 
124 		DataVec4* const pData = static_cast<DataVec4*>(alloc.getHostPtr());
125 		for(int ndx = 0; ndx < m_numDrawVertices; ++ndx)
126 		{
127 			pData[ndx].pos = m_vertexPosData[ndx];
128 			pData[ndx].color = m_vertexAttrData[ndx];
129 		}
130 		flushAlloc(vk, device, alloc);
131 		// No barrier needed, flushed memory is automatically visible
132 	}
133 
134 	// Draw commands
135 	beginCommandBuffer(vk, *cmdBuffer);
136 
137 	// Change color attachment image layout
138 	{
139 		const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
140 				(VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
141 				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
142 				*colorAttachmentImage, colorSubRange);
143 
144 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
145 						0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
146 	}
147 
148 	// Begin render pass
149 	{
150 		const VkRect2D renderArea = {
151 				makeOffset2D(0, 0),
152 				makeExtent2D(resolution.x(), resolution.y()),
153 			};
154 			const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
155 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
156 	}
157 
158 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
159 	{
160 		const VkBuffer buffers[] = { vertexBuffer.get()};
161 		const VkDeviceSize offsets[] = { vertexPositionsOffset };
162 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(buffers), buffers, offsets);
163 	}
164 
165 	bindDescriptorSets(vk, device, memAlloc, *cmdBuffer, *pipelineLayout);
166 
167 	drawCommand (*cmdBuffer);
168 	endRenderPass(vk, *cmdBuffer);
169 
170 	// Copy render result to a host-visible buffer
171 	copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, resolution);
172 
173 	endCommandBuffer(vk, *cmdBuffer);
174 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
175 
176 	{
177 		// Log the result image.
178 		const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
179 		invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes);
180 		const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), resolution.x(), resolution.y(), 1, colorBufferAlloc.getHostPtr());
181 
182 		if (!compareWithFileImage(m_context, imagePixelAccess, m_name))
183 			return TestStatus::fail("Fail");
184 	}
185 
186 	return TestStatus::pass("Pass");
187 }
188 
createPipelineLayout(const DeviceInterface & vk,const VkDevice device)189 Move<VkPipelineLayout> GeometryExpanderRenderTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device)
190 {
191 	return makePipelineLayout(vk, device);
192 }
193 
drawCommand(const VkCommandBuffer & cmdBuffer)194 void GeometryExpanderRenderTestInstance::drawCommand (const VkCommandBuffer& cmdBuffer)
195 {
196 	const DeviceInterface& vk = m_context.getDeviceInterface();
197 	vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numDrawVertices), 1u, 0u, 0u);
198 }
199 
200 } // geometry
201 } // vkt
202