1 /*-------------------------------------------------------------------------
2  * Vulkan CTS Framework
3  * --------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Google Inc.
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 Utility for generating simple work
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawUtil.hpp"
26 #include "rrMultisamplePixelBufferAccess.hpp"
27 #include "vkBufferWithMemory.hpp"
28 #include "vkImageWithMemory.hpp"
29 #include "vkBarrierUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "rrRenderer.hpp"
34 #include "rrRenderState.hpp"
35 #include "rrPrimitiveTypes.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuTestLog.hpp"
38 #include "deArrayUtil.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 
42 namespace vkt
43 {
44 namespace drawutil
45 {
46 
47 using namespace de;
48 using namespace tcu;
49 using namespace vk;
50 
mapCompareOp(rr::TestFunc compareFunc)51 static VkCompareOp mapCompareOp (rr::TestFunc compareFunc)
52 {
53 	switch (compareFunc)
54 	{
55 		case rr::TESTFUNC_NEVER:				return VK_COMPARE_OP_NEVER;
56 		case rr::TESTFUNC_LESS:					return VK_COMPARE_OP_LESS;
57 		case rr::TESTFUNC_EQUAL:				return VK_COMPARE_OP_EQUAL;
58 		case rr::TESTFUNC_LEQUAL:				return VK_COMPARE_OP_LESS_OR_EQUAL;
59 		case rr::TESTFUNC_GREATER:				return VK_COMPARE_OP_GREATER;
60 		case rr::TESTFUNC_NOTEQUAL:				return VK_COMPARE_OP_NOT_EQUAL;
61 		case rr::TESTFUNC_GEQUAL:				return VK_COMPARE_OP_GREATER_OR_EQUAL;
62 		case rr::TESTFUNC_ALWAYS:				return VK_COMPARE_OP_ALWAYS;
63 		default:
64 			DE_ASSERT(false);
65 	}
66 	return VK_COMPARE_OP_LAST;
67 }
68 
mapVkPrimitiveToRRPrimitive(const vk::VkPrimitiveTopology & primitiveTopology)69 rr::PrimitiveType mapVkPrimitiveToRRPrimitive(const vk::VkPrimitiveTopology& primitiveTopology)
70 {
71 	static const rr::PrimitiveType primitiveTypeTable[] =
72 	{
73 		rr::PRIMITIVETYPE_POINTS,
74 		rr::PRIMITIVETYPE_LINES,
75 		rr::PRIMITIVETYPE_LINE_STRIP,
76 		rr::PRIMITIVETYPE_TRIANGLES,
77 		rr::PRIMITIVETYPE_TRIANGLE_STRIP,
78 		rr::PRIMITIVETYPE_TRIANGLE_FAN,
79 		rr::PRIMITIVETYPE_LINES_ADJACENCY,
80 		rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY,
81 		rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY,
82 		rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY
83 	};
84 
85 	return de::getSizedArrayElement<vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST>(primitiveTypeTable, primitiveTopology);
86 }
87 
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)88 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
89 {
90 	const VkCommandBufferAllocateInfo info =
91 	{
92 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
93 		DE_NULL,											// const void*			pNext;
94 		commandPool,										// VkCommandPool		commandPool;
95 		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel	level;
96 		1u,													// deUint32				commandBufferCount;
97 	};
98 	return allocateCommandBuffer(vk, device, &info);
99 }
100 
getPrimitiveTopologyShortName(const VkPrimitiveTopology topology)101 std::string getPrimitiveTopologyShortName (const VkPrimitiveTopology topology)
102 {
103 	std::string name(getPrimitiveTopologyName(topology));
104 	return de::toLower(name.substr(22));
105 }
106 
FrameBufferState(deUint32 renderWidth_,deUint32 renderHeight_)107 FrameBufferState::FrameBufferState(deUint32 renderWidth_, deUint32 renderHeight_)
108 	: renderSize(renderWidth_, renderHeight_)
109 {
110 	DE_ASSERT(renderSize.x() != 0 && renderSize.y() != 0);
111 }
112 
PipelineState(const int subpixelBits_)113 PipelineState::PipelineState(const int subpixelBits_)
114 	: subpixelBits			(subpixelBits_)
115 {
116 }
117 
DrawCallData(const vk::VkPrimitiveTopology topology_,const std::vector<tcu::Vec4> & vertices_)118 DrawCallData::DrawCallData(const vk::VkPrimitiveTopology topology_, const std::vector<tcu::Vec4>&	vertices_)
119 	: topology(topology_), vertices(vertices_)
120 {
121 }
122 
ReferenceDrawContext(const FrameBufferState & framebufferState)123 ReferenceDrawContext::ReferenceDrawContext(const FrameBufferState& framebufferState)
124 	: DrawContext(framebufferState)
125 {
126 }
127 
~ReferenceDrawContext(void)128 ReferenceDrawContext::~ReferenceDrawContext (void)
129 {
130 }
131 
registerDrawObject(const PipelineState & pipelineState,std::shared_ptr<rr::VertexShader> & vertexShader,std::shared_ptr<rr::FragmentShader> & fragmentShader,const DrawCallData & drawCallData)132 void ReferenceDrawContext::registerDrawObject(const PipelineState& pipelineState, std::shared_ptr<rr::VertexShader>& vertexShader, std::shared_ptr<rr::FragmentShader>&	fragmentShader, const DrawCallData& drawCallData)
133 {
134 	m_pipelineStates.push_back(pipelineState);
135 	m_vertexShaders.push_back(vertexShader);
136 	m_fragmentShaders.push_back(fragmentShader);
137 	m_drawCallData.push_back(drawCallData);
138 }
139 
140 
draw(void)141 void ReferenceDrawContext::draw (void)
142 {
143 	DE_ASSERT(m_fragmentShaders.size() == m_vertexShaders.size());
144 	DE_ASSERT(m_vertexShaders.size() == m_drawCallData.size());
145 	DE_ASSERT(m_drawCallData.size() == m_pipelineStates.size());
146 
147 	m_refImage.setStorage(vk::mapVkFormat(m_framebufferState.colorFormat), m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y());
148 	tcu::clear(m_refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
149 
150 	const rr::MultisamplePixelBufferAccess	referenceColorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(m_refImage.getAccess());
151 	const rr::RenderTarget					renderTarget(referenceColorBuffer);
152 	const rr::Renderer						renderer;
153 	for(deUint32 objectNdx=0; objectNdx < m_drawCallData.size(); objectNdx++)
154 	{
155 		const rr::RenderState					renderState((rr::ViewportState(referenceColorBuffer)), m_pipelineStates[objectNdx].subpixelBits, rr::VIEWPORTORIENTATION_UPPER_LEFT);
156 		const rr::Program						program(m_vertexShaders[objectNdx].get(), m_fragmentShaders[objectNdx].get());
157 		const rr::VertexAttrib					vertexAttrib[] =
158 		{
159 			rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, m_drawCallData[objectNdx].vertices.data())
160 		};
161 
162 		renderer.draw(rr::DrawCommand(	renderState,
163 										renderTarget,
164 										program,
165 										DE_LENGTH_OF_ARRAY(vertexAttrib),
166 										&vertexAttrib[0],
167 										rr::PrimitiveList(mapVkPrimitiveToRRPrimitive(m_drawCallData[objectNdx].topology), (int)m_drawCallData[objectNdx].vertices.size(), 0)));
168 
169 	}
170 }
171 
getColorPixels(void) const172 tcu::ConstPixelBufferAccess ReferenceDrawContext::getColorPixels (void) const
173 {
174 	return tcu::ConstPixelBufferAccess( m_refImage.getAccess().getFormat(),
175 										m_refImage.getAccess().getWidth(),
176 										m_refImage.getAccess().getHeight(),
177 										m_refImage.getAccess().getDepth(),
178 										m_refImage.getAccess().getDataPtr());
179 }
180 
VulkanShader(const vk::VkShaderStageFlagBits stage_,const vk::ProgramBinary & binary_)181 VulkanShader::VulkanShader(const vk::VkShaderStageFlagBits stage_, const vk::ProgramBinary& binary_)
182 	: stage(stage_)
183 	, binary(&binary_)
184 {
185 }
186 
VulkanProgram(const std::vector<VulkanShader> & shaders_)187 VulkanProgram::VulkanProgram(const std::vector<VulkanShader>& shaders_)
188 	: shaders(shaders_)
189 {
190 }
191 
VulkanDrawContext(Context & context,const FrameBufferState & frameBufferState)192 VulkanDrawContext::VulkanDrawContext (Context&					context,
193 									  const FrameBufferState&	frameBufferState)
194 	: DrawContext	(frameBufferState)
195 	, m_context		(context)
196 {
197 	const DeviceInterface&	vk						= m_context.getDeviceInterface();
198 	const VkDevice			device					= m_context.getDevice();
199 	Allocator&				allocator				= m_context.getDefaultAllocator();
200 
201 	// Color attachment image
202 	{
203 		const VkImageUsageFlags usage					= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
204 		VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
205 		const VkImageCreateInfo	imageCreateInfo	=
206 		{
207 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,													// VkStructureType			sType;
208 			DE_NULL,																				// const void*				pNext;
209 			(VkImageCreateFlags)0,																	// VkImageCreateFlags		flags;
210 			VK_IMAGE_TYPE_2D,																		// VkImageType				imageType;
211 			m_framebufferState.colorFormat,															// VkFormat					format;
212 			makeExtent3D(m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(), 1u),	// VkExtent3D				extent;
213 			1u,																						// uint32_t					mipLevels;
214 			1u,																						// uint32_t					arrayLayers;
215 			(VkSampleCountFlagBits)m_framebufferState.numSamples,									// VkSampleCountFlagBits	samples;
216 			VK_IMAGE_TILING_OPTIMAL,																// VkImageTiling			tiling;
217 			usage,																					// VkImageUsageFlags		usage;
218 			VK_SHARING_MODE_EXCLUSIVE,																// VkSharingMode			sharingMode;
219 			0u,																						// uint32_t					queueFamilyIndexCount;
220 			DE_NULL,																				// const uint32_t*			pQueueFamilyIndices;
221 			VK_IMAGE_LAYOUT_UNDEFINED,																// VkImageLayout			initialLayout;
222 		};
223 
224 		m_colorImage		= MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
225 		m_colorImageView	= makeImageView(vk, device, **m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_framebufferState.colorFormat, colorSubresourceRange);
226 
227 		// Buffer to copy attachment data after rendering
228 
229 		const VkDeviceSize bitmapSize = tcu::getPixelSize(mapVkFormat(m_framebufferState.colorFormat)) * m_framebufferState.renderSize.x() * m_framebufferState.renderSize.y();
230 		m_colorAttachmentBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
231 			vk, device, allocator, makeBufferCreateInfo(bitmapSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
232 
233 		{
234 			const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
235 			deMemset(alloc.getHostPtr(), 0, (size_t)bitmapSize);
236 			flushAlloc(vk, device, alloc);
237 		}
238 	}
239 
240 	// Depth buffer - create image when user didn't deliver its own, but configured depthFormat
241 	vk::VkImageView depthImageView = m_framebufferState.depthImageView;
242 	if (!m_framebufferState.depthImageView && m_framebufferState.depthFormat != VK_FORMAT_UNDEFINED)
243 	{
244 		const VkImageUsageFlags usage					= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
245 		VkImageSubresourceRange	depthSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
246 
247 		const VkImageCreateInfo depthImageCreateInfo =
248 		{
249 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,													// VkStructureType			sType
250 			DE_NULL,																				// const void*				pNext
251 			(VkImageCreateFlags)0,																	// VkImageCreateFlags		flags
252 			VK_IMAGE_TYPE_2D,																		// VkIMageType				imageType
253 			m_framebufferState.depthFormat,															// VkFormat					format
254 			makeExtent3D(m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(), 1u),	// VkExtent3D				extent;
255 			1u,																						// uint32_t					mipLevels
256 			1u,																						// uint32_t					arrayLayers
257 			(VkSampleCountFlagBits)m_framebufferState.numSamples,									// VkSampleCountFlagsBits	samples
258 			VK_IMAGE_TILING_OPTIMAL,																// VkImageTiling			tiling
259 			usage,																					// VkImageUsageFlags		usage
260 			VK_SHARING_MODE_EXCLUSIVE,																// VkSharingMode			sharingMode
261 			0u,																						// uint32_t					queueFamilyIndexCount
262 			DE_NULL,																				// const uint32_t			pQueueFamilyIndices
263 			VK_IMAGE_LAYOUT_UNDEFINED																// VkImageLayout			initialLayout
264 		};
265 
266 		m_depthImage		= MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, depthImageCreateInfo, MemoryRequirement::Any));
267 		m_depthImageView	= makeImageView(vk, device, **m_depthImage, VK_IMAGE_VIEW_TYPE_2D, m_framebufferState.depthFormat, depthSubresourceRange);
268 		depthImageView		= *m_depthImageView;
269 	}
270 
271 	// Renderpass
272 	{
273 		std::vector<VkAttachmentDescription> attachmentDescriptions;
274 		const VkAttachmentDescription attachDescriptors[] =
275 		{
276 			{
277 				(VkAttachmentDescriptionFlags)0,						// VkAttachmentDescriptionFlags		flags;
278 				m_framebufferState.colorFormat,							// VkFormat							format;
279 				(VkSampleCountFlagBits)m_framebufferState.numSamples,	// VkSampleCountFlagBits			samples;
280 				VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp				loadOp;
281 				VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp				storeOp;
282 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// VkAttachmentLoadOp				stencilLoadOp;
283 				VK_ATTACHMENT_STORE_OP_DONT_CARE,						// VkAttachmentStoreOp				stencilStoreOp;
284 				VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout					initialLayout;
285 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout					finalLayout;
286 			},
287 			{
288 				(VkAttachmentDescriptionFlags)0,						// VkAttachmentDescriptionFlags		flags
289 				m_framebufferState.depthFormat,							// VkFormat							format
290 				(VkSampleCountFlagBits)m_framebufferState.numSamples,	// VkSampleCountFlagBits			samples
291 				VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp				loadOp
292 				VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp				storeOp
293 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// VkAttachmentLoadOp				stencilLoadOp
294 				VK_ATTACHMENT_STORE_OP_DONT_CARE,						// VkAttachmentStoreOp				stencilStoreOp
295 				VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout					initialLayout
296 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// VkImageLayout					finalLayout
297 			}
298 		};
299 
300 		const VkAttachmentReference attachmentReferences[] =
301 		{
302 			{
303 				0u,													// uint32_t			attachment
304 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout
305 			},
306 			{
307 				1u,													// uint32_t			attachment
308 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
309 			},
310 			{
311 				VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
312 				VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
313 			}
314 		};
315 
316 		attachmentDescriptions.push_back(attachDescriptors[0]);
317 		deUint32 depthReferenceNdx = 2;
318 		if (depthImageView != 0)
319 		{
320 			attachmentDescriptions.push_back(attachDescriptors[1]);
321 			depthReferenceNdx = 1;
322 		}
323 
324 		const VkSubpassDescription subpassDescription =
325 		{
326 			(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
327 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
328 			0u,													// deUint32							inputAttachmentCount;
329 			DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
330 			1u,													// deUint32							colorAttachmentCount;
331 			&attachmentReferences[0],							// const VkAttachmentReference*		pColorAttachments;
332 			DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
333 			&attachmentReferences[depthReferenceNdx],			// const VkAttachmentReference*		pDepthStencilAttachment;
334 			0u,													// deUint32							preserveAttachmentCount;
335 			DE_NULL												// const deUint32*					pPreserveAttachments;
336 		};
337 
338 		const VkRenderPassCreateInfo renderPassInfo =
339 		{
340 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
341 			DE_NULL,											// const void*						pNext;
342 			(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
343 			(deUint32)attachmentDescriptions.size(),			// deUint32							attachmentCount;
344 			attachmentDescriptions.data(),						// const VkAttachmentDescription*	pAttachments;
345 			1u,													// deUint32							subpassCount;
346 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
347 			0u,													// deUint32							dependencyCount;
348 			DE_NULL												// const VkSubpassDependency*		pDependencies;
349 		};
350 
351 		m_renderPass = createRenderPass(vk, device, &renderPassInfo);
352 	}
353 
354 	// Framebuffer
355 	{
356 		std::vector<VkImageView>	attachmentBindInfos;
357 		deUint32					numAttachments;
358 		attachmentBindInfos.push_back(*m_colorImageView);
359 		if (depthImageView!=0)
360 			attachmentBindInfos.push_back(depthImageView);
361 
362 		numAttachments = (deUint32)(attachmentBindInfos.size());
363 		const VkFramebufferCreateInfo framebufferInfo = {
364 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType						sType;
365 			DE_NULL,										// const void*							pNext;
366 			(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags				flags;
367 			*m_renderPass,									// VkRenderPass							renderPass;
368 			numAttachments,									// uint32_t								attachmentCount;
369 			&attachmentBindInfos[0],						// const VkImageView*					pAttachments;
370 			m_framebufferState.renderSize.x(),				// uint32_t								width;
371 			m_framebufferState.renderSize.y(),				// uint32_t								height;
372 			1u,												// uint32_t								layers;
373 		};
374 
375 		m_framebuffer = createFramebuffer(vk, device, &framebufferInfo);
376 	}
377 
378 	// Command buffer
379 	m_cmdPool	= makeCommandPool(vk, device, m_context.getUniversalQueueFamilyIndex());
380 	m_cmdBuffer	= makeCommandBuffer(vk, device, *m_cmdPool);
381 }
382 
~VulkanDrawContext(void)383 VulkanDrawContext::~VulkanDrawContext (void)
384 {
385 }
386 
registerDrawObject(const PipelineState & pipelineState,const VulkanProgram & vulkanProgram,const DrawCallData & drawCallData)387 void VulkanDrawContext::registerDrawObject(const PipelineState& pipelineState, const VulkanProgram& vulkanProgram, const DrawCallData& drawCallData)
388 {
389 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
390 	const VkDevice			device		= m_context.getDevice();
391 	Allocator&				allocator	= m_context.getDefaultAllocator();
392 	auto					object		= std::make_shared<RenderObject>();
393 
394 	// Vertex buffer
395 	{
396 		const VkDeviceSize bufferSize	= drawCallData.vertices.size() * sizeof(drawCallData.vertices[0]);
397 		object->vertexBuffer				= MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
398 		object->vertexCount				= static_cast<deUint32>(drawCallData.vertices.size());
399 		const Allocation& alloc			= object->vertexBuffer->getAllocation();
400 		deMemcpy(alloc.getHostPtr(), &drawCallData.vertices[0], (size_t)bufferSize);
401 		flushAlloc(vk, device, alloc);
402 	}
403 
404 	// bind descriptor sets
405 	{
406 		object->pipelineLayout = makePipelineLayout(vk, device, vulkanProgram.descriptorSetLayout);
407 	}
408 
409 	// Graphics pipeline
410 	{
411 		VkShaderModule	vertShader			= DE_NULL;
412 		VkShaderModule	tessControlShader	= DE_NULL;
413 		VkShaderModule	tessEvalShader		= DE_NULL;
414 		VkShaderModule	geomShader			= DE_NULL;
415 		VkShaderModule	fragShader			= DE_NULL;
416 
417 		DE_ASSERT(drawCallData.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST || pipelineState.numPatchControlPoints > 0);
418 
419 		const std::vector<VkViewport>	viewports(1, makeViewport(m_framebufferState.renderSize));
420 		const std::vector<VkRect2D>		scissors(1, makeRect2D(m_framebufferState.renderSize));
421 
422 		VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
423 		{
424 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
425 			DE_NULL,														// const void*								pNext;
426 			(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags	flags;
427 			pipelineState.depthClampEnable,									// VkBool32									depthClampEnable;
428 			VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
429 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
430 			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
431 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
432 			VK_FALSE,														// VkBool32									depthBiasEnable;
433 			0.0f,															// float									depthBiasConstantFactor;
434 			0.0f,															// float									depthBiasClamp;
435 			0.0f,															// float									depthBiasSlopeFactor;
436 			pipelineState.lineWidth,										// float									lineWidth;
437 		};
438 
439 		VkPipelineRasterizationDepthClipStateCreateInfoEXT pipelineRasterizationDepthCliptateInfo =
440 		{
441 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT,	// VkStructureType										sType;
442 			DE_NULL,																	// const void*											pNext;
443 			(VkPipelineRasterizationDepthClipStateCreateFlagsEXT)0,						// VkPipelineRasterizationDepthClipStateCreateFlagsEXT	flags;
444 			pipelineState.depthClipEnable,												// VkBool32												depthClipEnable;
445 		};
446 		if (pipelineState.explicitDepthClipEnable)
447 			pipelineRasterizationStateInfo.pNext = &pipelineRasterizationDepthCliptateInfo;
448 
449 		const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
450 		{
451 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
452 			DE_NULL,													// const void*								pNext;
453 			(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
454 			(VkSampleCountFlagBits)m_framebufferState.numSamples,		// VkSampleCountFlagBits					rasterizationSamples;
455 			pipelineState.sampleShadingEnable ? VK_TRUE : VK_FALSE,		// VkBool32									sampleShadingEnable;
456 			pipelineState.sampleShadingEnable ? 1.0f : 0.0f,			// float									minSampleShading;
457 			DE_NULL,													// const VkSampleMask*						pSampleMask;
458 			VK_FALSE,													// VkBool32									alphaToCoverageEnable;
459 			VK_FALSE													// VkBool32									alphaToOneEnable;
460 		};
461 
462 		const VkStencilOpState stencilOpState = makeStencilOpState(
463 			VK_STENCIL_OP_KEEP,		// stencil fail
464 			VK_STENCIL_OP_KEEP,		// depth & stencil pass
465 			VK_STENCIL_OP_KEEP,		// depth only fail
466 			VK_COMPARE_OP_NEVER,	// compare op
467 			0u,						// compare mask
468 			0u,						// write mask
469 			0u);					// reference
470 
471 		if (pipelineState.depthBoundsTestEnable && !m_context.getDeviceFeatures().depthBounds)
472 			TCU_THROW(NotSupportedError, "depthBounds not supported");
473 
474 		const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
475 		{
476 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
477 			DE_NULL,													// const void*								pNext;
478 			(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
479 			pipelineState.depthTestEnable,								// VkBool32									depthTestEnable;
480 			pipelineState.depthWriteEnable,								// VkBool32									depthWriteEnable;
481 			mapCompareOp(pipelineState.compareOp),						// VkCompareOp								depthCompareOp;
482 			pipelineState.depthBoundsTestEnable,						// VkBool32									depthBoundsTestEnable
483 			VK_FALSE,													// VkBool32									stencilTestEnable;
484 			stencilOpState,												// VkStencilOpState							front;
485 			stencilOpState,												// VkStencilOpState							back;
486 			0.0f,														// float									minDepthBounds;
487 			1.0f,														// float									maxDepthBounds;
488 		};
489 
490 		const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
491 		const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
492 		{
493 			pipelineState.blendEnable,			// VkBool32					blendEnable;
494 			VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcColorBlendFactor;
495 			VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstColorBlendFactor;
496 			VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
497 			VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcAlphaBlendFactor;
498 			VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstAlphaBlendFactor;
499 			VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
500 			colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
501 		};
502 
503 		const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
504 		{
505 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
506 			DE_NULL,													// const void*									pNext;
507 			(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
508 			VK_FALSE,													// VkBool32										logicOpEnable;
509 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
510 			1u,															// deUint32										attachmentCount;
511 			&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
512 			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
513 		};
514 
515 		VkShaderStageFlags stageFlags = (VkShaderStageFlags)0;
516 
517 		DE_ASSERT(vulkanProgram.shaders.size() <= RenderObject::MAX_NUM_SHADER_MODULES);
518 		for (deUint32 shaderNdx = 0; shaderNdx < vulkanProgram.shaders.size(); ++shaderNdx)
519 		{
520 			object->shaderModules[shaderNdx] = createShaderModule(vk, device, *vulkanProgram.shaders[shaderNdx].binary, (VkShaderModuleCreateFlags)0);
521 
522 			stageFlags |= vulkanProgram.shaders[shaderNdx].stage;
523 
524 			switch (vulkanProgram.shaders[shaderNdx].stage)
525 			{
526 			case VK_SHADER_STAGE_VERTEX_BIT:
527 				vertShader = *object->shaderModules[shaderNdx];
528 				break;
529 			case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
530 				tessControlShader = *object->shaderModules[shaderNdx];
531 				break;
532 			case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
533 				tessEvalShader = *object->shaderModules[shaderNdx];
534 				break;
535 			case VK_SHADER_STAGE_GEOMETRY_BIT:
536 				geomShader = *object->shaderModules[shaderNdx];
537 				break;
538 			default:
539 				DE_ASSERT(vulkanProgram.shaders[shaderNdx].stage == VK_SHADER_STAGE_FRAGMENT_BIT);
540 				fragShader = *object->shaderModules[shaderNdx];
541 				break;
542 			}
543 		}
544 
545 		DE_ASSERT(
546 			(drawCallData.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ||
547 			(stageFlags & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)));
548 
549 		object->pipeline = makeGraphicsPipeline(vk,										// const DeviceInterface&                        vk
550 												device,									// const VkDevice                                device
551 												*(object->pipelineLayout),				// const VkPipelineLayout                        pipelineLayout
552 												vertShader,								// const VkShaderModule                          vertexShaderModule
553 												tessControlShader,						// const VkShaderModule                          tessellationControlShaderModule
554 												tessEvalShader,							// const VkShaderModule                          tessellationEvalShaderModule
555 												geomShader,								// const VkShaderModule                          geometryShaderModule
556 												fragShader,								// const VkShaderModule                          fragmentShaderModule
557 												*m_renderPass,							// const VkRenderPass                            renderPass
558 												viewports,								// const std::vector<VkViewport>&                viewports
559 												scissors,								// const std::vector<VkRect2D>&                  scissors
560 												drawCallData.topology,					// const VkPrimitiveTopology                     topology
561 												0u,										// const deUint32                                subpass
562 												pipelineState.numPatchControlPoints,	// const deUint32                                patchControlPoints
563 												DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
564 												&pipelineRasterizationStateInfo,		// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
565 												&pipelineMultisampleStateInfo,			// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
566 												&pipelineDepthStencilStateInfo,			// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
567 												&pipelineColorBlendStateInfo);			// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
568 		object->descriptorSet		= vulkanProgram.descriptorSet;
569 		object->descriptorSetLayout	= vulkanProgram.descriptorSetLayout;
570 	}
571 	m_renderObjects.push_back(object);
572 }
573 
draw(void)574 void VulkanDrawContext::draw (void)
575 {
576 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
577 	const VkDevice			device		= m_context.getDevice();
578 	const VkQueue			queue		= m_context.getUniversalQueue();
579 	Allocator&				allocator	= m_context.getDefaultAllocator();
580 	tcu::TestLog&			log			= m_context.getTestContext().getLog();
581 
582 	// Record commands
583 	{
584 		const VkDeviceSize zeroOffset = 0ull;
585 
586 		beginCommandBuffer(vk, *m_cmdBuffer);
587 
588 		// Begin render pass
589 		if (!!m_framebufferState.depthImageView || !!*m_depthImageView)
590 			beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y()), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0.0f, 0);
591 		else
592 			beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y()), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
593 
594 		for (const auto& object : m_renderObjects)
595 		{
596 			if (!!object->descriptorSet)
597 				vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *(object->pipelineLayout), 0u, 1u, &(object->descriptorSet), 0u, DE_NULL);
598 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *(object->pipeline));
599 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &(**(object->vertexBuffer)), &zeroOffset);
600 			vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(object->vertexCount), 1u, 0u, 0u);
601 		}
602 		endRenderPass(vk, *m_cmdBuffer);
603 
604 		// Barrier: draw -> copy from image
605 		{
606 			const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
607 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
608 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
609 				**m_colorImage, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
610 
611 			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
612 				0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
613 		}
614 
615 		// Resolve multisample image
616 		{
617 			if (m_framebufferState.numSamples != VK_SAMPLE_COUNT_1_BIT)
618 			{
619 				const VkImageResolve imageResolve =
620 				{
621 					makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
622 					{ 0, 0, 0},
623 					makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
624 					{ 0, 0, 0},
625 					makeExtent3D(m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(), 1u)
626 				};
627 
628 				const VkImageCreateInfo resolveImageCreateInfo =
629 				{
630 					VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,				// VkStructureType			sType
631 					DE_NULL,											// const void*				pNext
632 					(VkImageCreateFlags)0,								// VkImageCreateFlags		flags
633 					VK_IMAGE_TYPE_2D,									// VkImageType				imageType
634 					m_framebufferState.colorFormat,						// VkFormat					format
635 					makeExtent3D(m_framebufferState.renderSize.x(),		// VkExtent3D				extent;
636 							m_framebufferState.renderSize.y(), 1u),
637 					1u,													// uint32_t					mipLevels
638 					1u,													// uint32_t					arrayLayers
639 					VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits	samples
640 					VK_IMAGE_TILING_OPTIMAL,							// VkImaageTiling			tiling
641 					VK_IMAGE_USAGE_TRANSFER_DST_BIT |					// VkImageUsageFlags		usage
642 					VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
643 					VK_SHARING_MODE_EXCLUSIVE,							// VkSharingModeExclusive	sharingMode
644 					0u,													// uint32_t					queueFamilyIndexCount
645 					DE_NULL,											// const uint32_t*			pQueueFamilyIndices
646 					VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout			initialLayout
647 				};
648 
649 				m_resolveImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, resolveImageCreateInfo, MemoryRequirement::Any));
650 
651 				const VkImageMemoryBarrier resolveBarrier = makeImageMemoryBarrier(
652 						0u, VK_ACCESS_TRANSFER_WRITE_BIT,
653 						VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
654 						**m_resolveImage, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
655 
656 				vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
657 						0u, DE_NULL, 0u, DE_NULL, 1u, &resolveBarrier);
658 
659 				vk.cmdResolveImage(*m_cmdBuffer, **m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
660 						**m_resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &imageResolve);
661 
662 				const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
663 					VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
664 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
665 					**m_resolveImage, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
666 
667 				vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
668 					0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
669 			}
670 			else
671 				m_resolveImage = m_colorImage;
672 
673 			const VkBufferImageCopy copyRegion = makeBufferImageCopy(
674 				makeExtent3D(m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(), 1u),
675 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
676 			vk.cmdCopyImageToBuffer(*m_cmdBuffer, **m_resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_colorAttachmentBuffer, 1u, &copyRegion);
677 		}
678 
679 		// Barrier: copy to buffer -> host read
680 		{
681 			const VkBufferMemoryBarrier barrier = makeBufferMemoryBarrier(
682 				VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
683 				**m_colorAttachmentBuffer, 0ull, VK_WHOLE_SIZE);
684 
685 			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
686 				0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
687 		}
688 
689 		endCommandBuffer(vk, *m_cmdBuffer);
690 	}
691 
692 
693 	submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
694 
695 	log << tcu::LogImageSet("attachments", "") << tcu::LogImage("color0", "", getColorPixels()) << tcu::TestLog::EndImageSet;
696 }
697 
getColorPixels(void) const698 tcu::ConstPixelBufferAccess VulkanDrawContext::getColorPixels (void) const
699 {
700 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
701 	const VkDevice			device		= m_context.getDevice();
702 
703 	const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
704 	invalidateAlloc(vk, device, alloc);
705 
706 	return tcu::ConstPixelBufferAccess(mapVkFormat(m_framebufferState.colorFormat), m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(), 1u, alloc.getHostPtr());
707 }
708 } // drawutil
709 } // vkt
710