vktShaderRender.cpp revision 9931d9632ce1e900213ddd41ebd25a36cc93536e
1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and/or associated documentation files (the
10 * "Materials"), to deal in the Materials without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Materials, and to
13 * permit persons to whom the Materials are furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice(s) and this permission notice shall be included
17 * in all copies or substantial portions of the Materials.
18 *
19 * The Materials are Confidential Information as defined by the
20 * Khronos Membership Agreement until designated non-confidential by Khronos,
21 * at which point this condition clause shall be removed.
22 *
23 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
30 *
31 *//*!
32 * \file
33 * \brief Vulkan ShaderRenderCase
34 *//*--------------------------------------------------------------------*/
35
36#include "vktShaderRender.hpp"
37
38#include "tcuImageCompare.hpp"
39#include "tcuImageIO.hpp"
40#include "tcuTestLog.hpp"
41#include "tcuTextureUtil.hpp"
42#include "tcuSurface.hpp"
43#include "tcuVector.hpp"
44
45#include "deFilePath.hpp"
46#include "deMath.h"
47#include "deUniquePtr.hpp"
48
49#include "vkDeviceUtil.hpp"
50#include "vkImageUtil.hpp"
51#include "vkPlatform.hpp"
52#include "vkQueryUtil.hpp"
53#include "vkRef.hpp"
54#include "vkRefUtil.hpp"
55#include "vkStrUtil.hpp"
56#include "vkTypeUtil.hpp"
57
58#include <vector>
59#include <string>
60
61namespace vkt
62{
63namespace sr
64{
65
66using namespace vk;
67
68namespace
69{
70
71static const int		GRID_SIZE			= 2;
72static const deUint32	MAX_RENDER_WIDTH	= 128;
73static const deUint32	MAX_RENDER_HEIGHT	= 128;
74static const tcu::Vec4	DEFAULT_CLEAR_COLOR	= tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
75
76static bool isSupportedLinearTilingFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
77{
78	VkFormatProperties formatProps;
79
80	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
81
82	return (formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
83}
84
85static bool isSupportedOptimalTilingFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
86{
87	VkFormatProperties formatProps;
88
89	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
90
91	return (formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
92}
93
94static VkImageMemoryBarrier createImageMemoryBarrier (const VkImage&	image,
95													  VkAccessFlags		srcAccessMask,
96													  VkAccessFlags		dstAccessMask,
97													  VkImageLayout		oldLayout,
98													  VkImageLayout		newLayout)
99{
100	VkImageMemoryBarrier imageMemoryBarrier	=
101	{
102		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType				sType;
103		DE_NULL,									// const void*					pNext;
104		srcAccessMask,								// VkAccessFlags				srcAccessMask;
105		dstAccessMask,								// VkAccessFlags				dstAccessMask;
106		oldLayout,									// VkImageLayout				oldLayout;
107		newLayout,									// VkImageLayout				newLayout;
108		VK_QUEUE_FAMILY_IGNORED,					// deUint32						srcQueueFamilyIndex;
109		VK_QUEUE_FAMILY_IGNORED,					// deUint32						dstQueueFamilyIndex;
110		image,										// VkImage						image;
111		{
112			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
113			0,							// deUint32				baseMipLevel;
114			1,							// deUint32				mipLevels;
115			0,							// deUint32				baseArrayLayer;
116			1							// deUint32				arraySize;
117		}											// VkImageSubresourceRange		subresourceRange;
118	};
119	return imageMemoryBarrier;
120}
121
122} // anonymous
123
124// QuadGrid.
125
126class QuadGrid
127{
128public:
129											QuadGrid				(int									gridSize,
130																	 int									screenWidth,
131																	 int									screenHeight,
132																	 const tcu::Vec4&						constCoords,
133																	 const std::vector<tcu::Mat4>&			userAttribTransforms,
134																	 const std::vector<TextureBindingSp>&	textures);
135											~QuadGrid				(void);
136
137	int										getGridSize				(void) const { return m_gridSize; }
138	int										getNumVertices			(void) const { return m_numVertices; }
139	int										getNumTriangles			(void) const { return m_numTriangles; }
140	const tcu::Vec4&						getConstCoords			(void) const { return m_constCoords; }
141	const std::vector<tcu::Mat4>			getUserAttribTransforms	(void) const { return m_userAttribTransforms; }
142	const std::vector<TextureBindingSp>&	getTextures				(void) const { return m_textures; }
143
144	const tcu::Vec4*						getPositions			(void) const { return &m_positions[0]; }
145	const float*							getAttribOne			(void) const { return &m_attribOne[0]; }
146	const tcu::Vec4*						getCoords				(void) const { return &m_coords[0]; }
147	const tcu::Vec4*						getUnitCoords			(void) const { return &m_unitCoords[0]; }
148
149	const tcu::Vec4*						getUserAttrib			(int attribNdx) const { return &m_userAttribs[attribNdx][0]; }
150	const deUint16*							getIndices				(void) const { return &m_indices[0]; }
151
152	tcu::Vec4								getCoords				(float sx, float sy) const;
153	tcu::Vec4								getUnitCoords			(float sx, float sy) const;
154
155	int										getNumUserAttribs		(void) const { return (int)m_userAttribTransforms.size(); }
156	tcu::Vec4								getUserAttrib			(int attribNdx, float sx, float sy) const;
157
158private:
159	const int								m_gridSize;
160	const int								m_numVertices;
161	const int								m_numTriangles;
162	const tcu::Vec4							m_constCoords;
163	const std::vector<tcu::Mat4>			m_userAttribTransforms;
164
165	const std::vector<TextureBindingSp>&	m_textures;
166
167	std::vector<tcu::Vec4>					m_screenPos;
168	std::vector<tcu::Vec4>					m_positions;
169	std::vector<tcu::Vec4>					m_coords;		//!< Near-unit coordinates, roughly [-2.0 .. 2.0].
170	std::vector<tcu::Vec4>					m_unitCoords;	//!< Positive-only coordinates [0.0 .. 1.5].
171	std::vector<float>						m_attribOne;
172	std::vector<tcu::Vec4>					m_userAttribs[ShaderEvalContext::MAX_TEXTURES];
173	std::vector<deUint16>					m_indices;
174};
175
176QuadGrid::QuadGrid (int										gridSize,
177					int										width,
178					int										height,
179					const tcu::Vec4&						constCoords,
180					const std::vector<tcu::Mat4>&			userAttribTransforms,
181					const std::vector<TextureBindingSp>&	textures)
182	: m_gridSize				(gridSize)
183	, m_numVertices				((gridSize + 1) * (gridSize + 1))
184	, m_numTriangles			(gridSize * gridSize * 2)
185	, m_constCoords				(constCoords)
186	, m_userAttribTransforms	(userAttribTransforms)
187	, m_textures				(textures)
188{
189	const tcu::Vec4 viewportScale	((float)width, (float)height, 0.0f, 0.0f);
190
191	// Compute vertices.
192	m_screenPos.resize(m_numVertices);
193	m_positions.resize(m_numVertices);
194	m_coords.resize(m_numVertices);
195	m_unitCoords.resize(m_numVertices);
196	m_attribOne.resize(m_numVertices);
197
198	// User attributes.
199	for (int attrNdx = 0; attrNdx < DE_LENGTH_OF_ARRAY(m_userAttribs); attrNdx++)
200		m_userAttribs[attrNdx].resize(m_numVertices);
201
202	for (int y = 0; y < gridSize+1; y++)
203	for (int x = 0; x < gridSize+1; x++)
204	{
205		float		sx			= (float)x / (float)gridSize;
206		float		sy			= (float)y / (float)gridSize;
207		float		fx			= 2.0f * sx - 1.0f;
208		float		fy			= 2.0f * sy - 1.0f;
209		int			vtxNdx		= ((y * (gridSize+1)) + x);
210
211		m_positions[vtxNdx]		= tcu::Vec4(fx, fy, 0.0f, 1.0f);
212		m_coords[vtxNdx]		= getCoords(sx, sy);
213		m_unitCoords[vtxNdx]	= getUnitCoords(sx, sy);
214		m_attribOne[vtxNdx]		= 1.0f;
215
216		m_screenPos[vtxNdx]		= tcu::Vec4(sx, sy, 0.0f, 1.0f) * viewportScale;
217
218		for (int attribNdx = 0; attribNdx < getNumUserAttribs(); attribNdx++)
219			m_userAttribs[attribNdx][vtxNdx] = getUserAttrib(attribNdx, sx, sy);
220	}
221
222	// Compute indices.
223	m_indices.resize(3 * m_numTriangles);
224	for (int y = 0; y < gridSize; y++)
225	for (int x = 0; x < gridSize; x++)
226	{
227		int stride				= gridSize + 1;
228		int v00					= (y * stride) + x;
229		int v01					= (y * stride) + x + 1;
230		int v10					= ((y+1) * stride) + x;
231		int v11					= ((y+1) * stride) + x + 1;
232
233		int baseNdx				= ((y * gridSize) + x) * 6;
234		m_indices[baseNdx + 0]	= (deUint16)v10;
235		m_indices[baseNdx + 1]	= (deUint16)v00;
236		m_indices[baseNdx + 2]	= (deUint16)v01;
237
238		m_indices[baseNdx + 3]	= (deUint16)v10;
239		m_indices[baseNdx + 4]	= (deUint16)v01;
240		m_indices[baseNdx + 5]	= (deUint16)v11;
241	}
242}
243
244QuadGrid::~QuadGrid (void)
245{
246}
247
248inline tcu::Vec4 QuadGrid::getCoords (float sx, float sy) const
249{
250	const float fx = 2.0f * sx - 1.0f;
251	const float fy = 2.0f * sy - 1.0f;
252	return tcu::Vec4(fx, fy, -fx + 0.33f*fy, -0.275f*fx - fy);
253}
254
255inline tcu::Vec4 QuadGrid::getUnitCoords (float sx, float sy) const
256{
257	return tcu::Vec4(sx, sy, 0.33f*sx + 0.5f*sy, 0.5f*sx + 0.25f*sy);
258}
259
260inline tcu::Vec4 QuadGrid::getUserAttrib (int attribNdx, float sx, float sy) const
261{
262	// homogeneous normalized screen-space coordinates
263	return m_userAttribTransforms[attribNdx] * tcu::Vec4(sx, sy, 0.0f, 1.0f);
264}
265
266// TextureBinding
267
268TextureBinding::TextureBinding (const tcu::Archive&	archive,
269								const char*			filename,
270								const Type			type,
271								const tcu::Sampler&	sampler)
272	: m_type	(type)
273	, m_sampler	(sampler)
274{
275	switch(m_type)
276	{
277		case TYPE_2D: m_binding.tex2D = loadTexture2D(archive, filename).release(); break;
278		default:
279			DE_FATAL("Unsupported texture type");
280	}
281}
282
283TextureBinding::~TextureBinding (void)
284{
285	switch(m_type)
286	{
287		case TYPE_2D: delete m_binding.tex2D; break;
288		default: break;
289	}
290}
291
292
293de::MovePtr<tcu::Texture2D> TextureBinding::loadTexture2D (const tcu::Archive& archive, const char* filename)
294{
295	tcu::TextureLevel level;
296	tcu::ImageIO::loadImage(level, archive, filename);
297
298	TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
299					   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
300
301	// \todo [2015-10-08 elecro] for some reason we get better when using RGBA texture even in RGB case, this needs to be investigated
302	de::MovePtr<tcu::Texture2D> texture(new tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth(), level.getHeight()));
303
304	// Fill level 0.
305	texture->allocLevel(0);
306	tcu::copy(texture->getLevel(0), level.getAccess());
307
308	return texture;
309}
310
311// ShaderEvalContext.
312
313ShaderEvalContext::ShaderEvalContext (const QuadGrid& quadGrid)
314	: constCoords	(quadGrid.getConstCoords())
315	, isDiscarded	(false)
316	, m_quadGrid	(quadGrid)
317{
318	const std::vector<TextureBindingSp>& bindings = m_quadGrid.getTextures();
319	DE_ASSERT((int)bindings.size() <= MAX_TEXTURES);
320
321	// Fill in texture array.
322	for (int ndx = 0; ndx < (int)bindings.size(); ndx++)
323	{
324		const TextureBinding& binding = *bindings[ndx];
325
326		if (binding.getType() == TextureBinding::TYPE_NONE)
327			continue;
328
329		textures[ndx].sampler = binding.getSampler();
330
331		switch (binding.getType())
332		{
333			case TextureBinding::TYPE_2D:		textures[ndx].tex2D			= &binding.get2D();		break;
334			// \todo [2015-09-07 elecro] Add support for the other binding types
335			/*
336			case TextureBinding::TYPE_CUBE_MAP:	textures[ndx].texCube		= binding.getCube();	break;
337			case TextureBinding::TYPE_2D_ARRAY:	textures[ndx].tex2DArray	= binding.get2DArray();	break;
338			case TextureBinding::TYPE_3D:		textures[ndx].tex3D			= binding.get3D();		break;
339			*/
340			default:
341				TCU_THROW(InternalError, "Handling of texture binding type not implemented");
342		}
343	}
344}
345
346ShaderEvalContext::~ShaderEvalContext (void)
347{
348}
349
350void ShaderEvalContext::reset (float sx, float sy)
351{
352	// Clear old values
353	color		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
354	isDiscarded	= false;
355
356	// Compute coords
357	coords		= m_quadGrid.getCoords(sx, sy);
358	unitCoords	= m_quadGrid.getUnitCoords(sx, sy);
359
360	// Compute user attributes.
361	const int numAttribs = m_quadGrid.getNumUserAttribs();
362	DE_ASSERT(numAttribs <= MAX_USER_ATTRIBS);
363	for (int attribNdx = 0; attribNdx < numAttribs; attribNdx++)
364		in[attribNdx] = m_quadGrid.getUserAttrib(attribNdx, sx, sy);
365}
366
367tcu::Vec4 ShaderEvalContext::texture2D (int unitNdx, const tcu::Vec2& texCoords)
368{
369	if (textures[unitNdx].tex2D)
370		return textures[unitNdx].tex2D->sample(textures[unitNdx].sampler, texCoords.x(), texCoords.y(), 0.0f);
371	else
372		return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
373}
374
375// ShaderEvaluator.
376
377ShaderEvaluator::ShaderEvaluator (void)
378	: m_evalFunc(DE_NULL)
379{
380}
381
382ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
383	: m_evalFunc(evalFunc)
384{
385}
386
387ShaderEvaluator::~ShaderEvaluator (void)
388{
389}
390
391void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
392{
393	DE_ASSERT(m_evalFunc);
394	m_evalFunc(ctx);
395}
396
397// UniformSetup.
398
399UniformSetup::UniformSetup (void)
400	: m_setupFunc(DE_NULL)
401{
402}
403
404UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
405	: m_setupFunc(setupFunc)
406{
407}
408
409UniformSetup::~UniformSetup (void)
410{
411}
412
413void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
414{
415	if (m_setupFunc)
416		m_setupFunc(instance, constCoords);
417}
418
419// ShaderRenderCase.
420
421ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
422									const std::string&			name,
423									const std::string&			description,
424									const bool					isVertexCase,
425									const ShaderEvalFunc		evalFunc,
426									const UniformSetup*			uniformSetup,
427									const AttributeSetupFunc	attribFunc)
428	: vkt::TestCase		(testCtx, name, description)
429	, m_isVertexCase	(isVertexCase)
430	, m_evaluator		(new ShaderEvaluator(evalFunc))
431	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
432	, m_attribFunc		(attribFunc)
433{}
434
435ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
436									const std::string&			name,
437									const std::string&			description,
438									const bool					isVertexCase,
439									const ShaderEvaluator*		evaluator,
440									const UniformSetup*			uniformSetup,
441									const AttributeSetupFunc	attribFunc)
442	: vkt::TestCase		(testCtx, name, description)
443	, m_isVertexCase	(isVertexCase)
444	, m_evaluator		(evaluator)
445	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
446	, m_attribFunc		(attribFunc)
447{}
448
449ShaderRenderCase::~ShaderRenderCase (void)
450{
451}
452
453void ShaderRenderCase::initPrograms (vk::SourceCollections& programCollection) const
454{
455	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
456	programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
457}
458
459TestInstance* ShaderRenderCase::createInstance (Context& context) const
460{
461	DE_ASSERT(m_evaluator != DE_NULL);
462	DE_ASSERT(m_uniformSetup != DE_NULL);
463	return new ShaderRenderCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_attribFunc);
464}
465
466// ShaderRenderCaseInstance.
467
468ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&					context,
469													const bool					isVertexCase,
470													const ShaderEvaluator&		evaluator,
471													const UniformSetup&			uniformSetup,
472													const AttributeSetupFunc	attribFunc)
473	: vkt::TestInstance	(context)
474	, m_clearColor		(DEFAULT_CLEAR_COLOR)
475	, m_memAlloc		(context.getDefaultAllocator())
476	, m_isVertexCase	(isVertexCase)
477	, m_evaluator		(evaluator)
478	, m_uniformSetup	(uniformSetup)
479	, m_attribFunc		(attribFunc)
480	, m_renderSize		(128, 128)
481	, m_colorFormat		(VK_FORMAT_R8G8B8A8_UNORM)
482{
483}
484
485ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
486{
487}
488
489tcu::TestStatus ShaderRenderCaseInstance::iterate (void)
490{
491	setup();
492
493	// Create quad grid.
494	const tcu::UVec2	viewportSize	= getViewportSize();
495	const int			width			= viewportSize.x();
496	const int			height			= viewportSize.y();
497
498	QuadGrid			quadGrid		(m_isVertexCase ? GRID_SIZE : 4, width, height, tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f), m_userAttribTransforms, m_textures);
499
500	// Render result.
501	tcu::Surface		resImage		(width, height);
502	render(resImage, quadGrid);
503
504	// Compute reference.
505	tcu::Surface		refImage		(width, height);
506	if (m_isVertexCase)
507		computeVertexReference(refImage, quadGrid);
508	else
509		computeFragmentReference(refImage, quadGrid);
510
511	// Compare.
512	const bool			compareOk		= compareImages(resImage, refImage, 0.05f);
513
514	if (compareOk)
515		return tcu::TestStatus::pass("Result image matches reference");
516	else
517		return tcu::TestStatus::fail("Image mismatch");
518}
519
520void ShaderRenderCaseInstance::setupUniformData (deUint32 bindingLocation, size_t size, const void* dataPtr)
521{
522	const VkDevice					vkDevice			= m_context.getDevice();
523	const DeviceInterface&			vk					= m_context.getDeviceInterface();
524	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
525
526	const VkBufferCreateInfo		uniformBufferParams	=
527	{
528		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
529		DE_NULL,									// const void*			pNext;
530		0u,											// VkBufferCreateFlags	flags;
531		size,										// VkDeviceSize			size;
532		VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
533		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
534		1u,											// deUint32				queueFamilyCount;
535		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
536	};
537
538	Move<VkBuffer>					buffer				= createBuffer(vk, vkDevice, &uniformBufferParams);
539	de::MovePtr<Allocation>			alloc				= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
540	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
541
542	deMemcpy(alloc->getHostPtr(), dataPtr, size);
543	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), size);
544
545	de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
546	uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
547	uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size);
548	uniformInfo->location = bindingLocation;
549	uniformInfo->buffer = VkBufferSp(new vk::Unique<VkBuffer>(buffer));
550	uniformInfo->alloc = AllocationSp(alloc.release());
551
552	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
553}
554
555void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, size_t dataSize, const void* data)
556{
557	m_descriptorSetLayoutBuilder.addSingleBinding(descriptorType, vk::VK_SHADER_STAGE_ALL);
558	m_descriptorPoolBuilder.addType(descriptorType);
559
560	setupUniformData(bindingLocation, dataSize, data);
561}
562
563void ShaderRenderCaseInstance::addAttribute (deUint32		bindingLocation,
564											 vk::VkFormat	format,
565											 deUint32		sizePerElement,
566											 deUint32		count,
567											 const void*	dataPtr)
568{
569	// Add binding specification
570	const deUint32							binding					= (deUint32)m_vertexBindingDescription.size();
571	const VkVertexInputBindingDescription	bindingDescription		=
572	{
573		binding,							// deUint32				binding;
574		sizePerElement,						// deUint32				stride;
575		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	stepRate;
576	};
577
578	m_vertexBindingDescription.push_back(bindingDescription);
579
580	// Add location and format specification
581	const VkVertexInputAttributeDescription	attributeDescription	=
582	{
583		bindingLocation,			// deUint32	location;
584		binding,					// deUint32	binding;
585		format,						// VkFormat	format;
586		0u,							// deUint32	offset;
587	};
588
589	m_vertexattributeDescription.push_back(attributeDescription);
590
591	// Upload data to buffer
592	const VkDevice							vkDevice				= m_context.getDevice();
593	const DeviceInterface&					vk						= m_context.getDeviceInterface();
594	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
595
596	const VkDeviceSize						inputSize				= sizePerElement * count;
597	const VkBufferCreateInfo				vertexBufferParams		=
598	{
599		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
600		DE_NULL,									// const void*			pNext;
601		0u,											// VkBufferCreateFlags	flags;
602		inputSize,									// VkDeviceSize			size;
603		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
604		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
605		1u,											// deUint32				queueFamilyCount;
606		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
607	};
608
609	Move<VkBuffer>							buffer					= createBuffer(vk, vkDevice, &vertexBufferParams);
610	de::MovePtr<vk::Allocation>				alloc					= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
611	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
612
613	deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
614	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize);
615
616	m_vertexBuffers.push_back(VkBufferSp(new vk::Unique<VkBuffer>(buffer)));
617	m_vertexBufferAllocs.push_back(AllocationSp(alloc.release()));
618}
619
620void ShaderRenderCaseInstance::useAttribute (deUint32 bindingLocation, BaseAttributeType type)
621{
622	const EnabledBaseAttribute attribute =
623	{
624		bindingLocation,	// deUint32				location;
625		type				// BaseAttributeType	type;
626	};
627	m_enabledBaseAttributes.push_back(attribute);
628}
629
630void ShaderRenderCaseInstance::setup (void)
631{
632}
633
634void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
635{
636	m_uniformSetup.setup(*this, constCoords);
637}
638
639void ShaderRenderCaseInstance::useUniform (deUint32 bindingLocation, BaseUniformType type)
640{
641	#define UNIFORM_CASE(type, value) case type: addUniform(bindingLocation, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, value); break
642
643	switch(type)
644	{
645		// Bool
646		UNIFORM_CASE(UB_FALSE,	0);
647		UNIFORM_CASE(UB_TRUE,	1);
648
649		// BVec4
650		UNIFORM_CASE(UB4_FALSE,	tcu::Vec4(0));
651		UNIFORM_CASE(UB4_TRUE,	tcu::Vec4(1));
652
653		// Integer
654		UNIFORM_CASE(UI_ZERO,	0);
655		UNIFORM_CASE(UI_ONE,	1);
656		UNIFORM_CASE(UI_TWO,	2);
657		UNIFORM_CASE(UI_THREE,	3);
658		UNIFORM_CASE(UI_FOUR,	4);
659		UNIFORM_CASE(UI_FIVE,	5);
660		UNIFORM_CASE(UI_SIX,	6);
661		UNIFORM_CASE(UI_SEVEN,	7);
662		UNIFORM_CASE(UI_EIGHT,	8);
663		UNIFORM_CASE(UI_ONEHUNDREDONE, 101);
664
665		// IVec2
666		UNIFORM_CASE(UI2_MINUS_ONE,	tcu::IVec2(-1));
667		UNIFORM_CASE(UI2_ZERO,		tcu::IVec2(0));
668		UNIFORM_CASE(UI2_ONE,		tcu::IVec2(1));
669		UNIFORM_CASE(UI2_TWO,		tcu::IVec2(2));
670		UNIFORM_CASE(UI2_THREE,		tcu::IVec2(3));
671		UNIFORM_CASE(UI2_FOUR,		tcu::IVec2(4));
672		UNIFORM_CASE(UI2_FIVE,		tcu::IVec2(5));
673
674		// IVec3
675		UNIFORM_CASE(UI3_MINUS_ONE,	tcu::IVec3(-1));
676		UNIFORM_CASE(UI3_ZERO,		tcu::IVec3(0));
677		UNIFORM_CASE(UI3_ONE,		tcu::IVec3(1));
678		UNIFORM_CASE(UI3_TWO,		tcu::IVec3(2));
679		UNIFORM_CASE(UI3_THREE,		tcu::IVec3(3));
680		UNIFORM_CASE(UI3_FOUR,		tcu::IVec3(4));
681		UNIFORM_CASE(UI3_FIVE,		tcu::IVec3(5));
682
683		// IVec4
684		UNIFORM_CASE(UI4_MINUS_ONE, tcu::IVec4(-1));
685		UNIFORM_CASE(UI4_ZERO,		tcu::IVec4(0));
686		UNIFORM_CASE(UI4_ONE,		tcu::IVec4(1));
687		UNIFORM_CASE(UI4_TWO,		tcu::IVec4(2));
688		UNIFORM_CASE(UI4_THREE,		tcu::IVec4(3));
689		UNIFORM_CASE(UI4_FOUR,		tcu::IVec4(4));
690		UNIFORM_CASE(UI4_FIVE,		tcu::IVec4(5));
691
692		// Float
693		UNIFORM_CASE(UF_ZERO,		0.0f);
694		UNIFORM_CASE(UF_ONE,		1.0f);
695		UNIFORM_CASE(UF_TWO,		2.0f);
696		UNIFORM_CASE(UF_THREE,		3.0f);
697		UNIFORM_CASE(UF_FOUR,		4.0f);
698		UNIFORM_CASE(UF_FIVE,		5.0f);
699		UNIFORM_CASE(UF_SIX,		6.0f);
700		UNIFORM_CASE(UF_SEVEN,		7.0f);
701		UNIFORM_CASE(UF_EIGHT,		8.0f);
702
703		UNIFORM_CASE(UF_HALF,		1.0f / 2.0f);
704		UNIFORM_CASE(UF_THIRD,		1.0f / 3.0f);
705		UNIFORM_CASE(UF_FOURTH,		1.0f / 4.0f);
706		UNIFORM_CASE(UF_FIFTH,		1.0f / 5.0f);
707		UNIFORM_CASE(UF_SIXTH,		1.0f / 6.0f);
708		UNIFORM_CASE(UF_SEVENTH,	1.0f / 7.0f);
709		UNIFORM_CASE(UF_EIGHTH,		1.0f / 8.0f);
710
711		// Vec2
712		UNIFORM_CASE(UV2_MINUS_ONE,	tcu::Vec2(-1.0f));
713		UNIFORM_CASE(UV2_ZERO,		tcu::Vec2(0.0f));
714		UNIFORM_CASE(UV2_ONE,		tcu::Vec2(1.0f));
715		UNIFORM_CASE(UV2_TWO,		tcu::Vec2(2.0f));
716		UNIFORM_CASE(UV2_THREE,		tcu::Vec2(3.0f));
717
718		UNIFORM_CASE(UV2_HALF,		tcu::Vec2(1.0f / 2.0f));
719
720		// Vec3
721		UNIFORM_CASE(UV3_MINUS_ONE,	tcu::Vec3(-1.0f));
722		UNIFORM_CASE(UV3_ZERO,		tcu::Vec3(0.0f));
723		UNIFORM_CASE(UV3_ONE,		tcu::Vec3(1.0f));
724		UNIFORM_CASE(UV3_TWO,		tcu::Vec3(2.0f));
725		UNIFORM_CASE(UV3_THREE,		tcu::Vec3(3.0f));
726
727		UNIFORM_CASE(UV3_HALF,		tcu::Vec3(1.0f / 2.0f));
728
729		// Vec4
730		UNIFORM_CASE(UV4_MINUS_ONE,	tcu::Vec4(-1.0f));
731		UNIFORM_CASE(UV4_ZERO,		tcu::Vec4(0.0f));
732		UNIFORM_CASE(UV4_ONE,		tcu::Vec4(1.0f));
733		UNIFORM_CASE(UV4_TWO,		tcu::Vec4(2.0f));
734		UNIFORM_CASE(UV4_THREE,		tcu::Vec4(3.0f));
735
736		UNIFORM_CASE(UV4_HALF,		tcu::Vec4(1.0f / 2.0f));
737
738		UNIFORM_CASE(UV4_BLACK,		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
739		UNIFORM_CASE(UV4_GRAY,		tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
740		UNIFORM_CASE(UV4_WHITE,		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
741
742		default:
743			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unknown Uniform type: " << type << tcu::TestLog::EndMessage;
744			break;
745	}
746
747	#undef UNIFORM_CASE
748}
749
750const tcu::UVec2 ShaderRenderCaseInstance::getViewportSize (void) const
751{
752	return tcu::UVec2(de::min(m_renderSize.x(), MAX_RENDER_WIDTH),
753					  de::min(m_renderSize.y(), MAX_RENDER_HEIGHT));
754}
755
756Move<VkImage> ShaderRenderCaseInstance::createImage2D (const tcu::Texture2D&	texture,
757													   const VkFormat			format,
758													   const VkImageUsageFlags	usage,
759													   const VkImageTiling		tiling)
760{
761	const VkDevice			vkDevice			= m_context.getDevice();
762	const DeviceInterface&	vk					= m_context.getDeviceInterface();
763	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
764
765	const VkImageCreateInfo	imageCreateInfo		=
766	{
767		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,						// VkStructureType			sType;
768		DE_NULL,													// const void*				pNext;
769		0,															// VkImageCreateFlags		flags;
770		VK_IMAGE_TYPE_2D,											// VkImageType				imageType;
771		format,														// VkFormat					format;
772		{
773			(deUint32)texture.getWidth(),
774			(deUint32)texture.getHeight(),
775			1u
776		},															// VkExtend3D				extent;
777		1u,															// deUint32					mipLevels;
778		1u,															// deUint32					arraySize;
779		VK_SAMPLE_COUNT_1_BIT,										// deUint32					samples;
780		tiling,														// VkImageTiling			tiling;
781		usage,														// VkImageUsageFlags		usage;
782		VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode			sharingMode;
783		1,															// deuint32					queueFamilyCount;
784		&queueFamilyIndex,											// const deUint32*			pQueueFamilyIndices;
785		VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			initialLayout;
786	};
787
788	Move<VkImage>			vkTexture			= createImage(vk, vkDevice, &imageCreateInfo);
789	return vkTexture;
790}
791
792de::MovePtr<Allocation> ShaderRenderCaseInstance::uploadImage2D (const tcu::Texture2D&	refTexture,
793																 const VkImage&			vkTexture)
794{
795	const VkDevice				vkDevice	= m_context.getDevice();
796	const DeviceInterface&		vk			= m_context.getDeviceInterface();
797
798	de::MovePtr<Allocation>		allocation	= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, vkTexture), MemoryRequirement::HostVisible);
799	VK_CHECK(vk.bindImageMemory(vkDevice, vkTexture, allocation->getMemory(), allocation->getOffset()));
800
801	const VkImageSubresource	subres				=
802	{
803		VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
804		0u,							// deUint32				mipLevel;
805		0u							// deUint32				arraySlice
806	};
807
808	VkSubresourceLayout layout;
809	vk.getImageSubresourceLayout(vkDevice, vkTexture, &subres, &layout);
810
811	tcu::ConstPixelBufferAccess	access		= refTexture.getLevel(0);
812	tcu::PixelBufferAccess		destAccess	(refTexture.getFormat(), refTexture.getWidth(), refTexture.getHeight(), 1, allocation->getHostPtr());
813
814	tcu::copy(destAccess, access);
815
816	flushMappedMemoryRange(vk, vkDevice, allocation->getMemory(), allocation->getOffset(), layout.size);
817
818	return allocation;
819}
820
821void ShaderRenderCaseInstance::copyTilingImageToOptimal	(const vk::VkImage&	srcImage,
822														 const vk::VkImage&	dstImage,
823														 deUint32			width,
824														 deUint32			height)
825{
826	const VkDevice						vkDevice			= m_context.getDevice();
827	const DeviceInterface&				vk					= m_context.getDeviceInterface();
828	const VkQueue						queue				= m_context.getUniversalQueue();
829	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
830
831	// Create command pool
832	const VkCommandPoolCreateInfo		cmdPoolParams		=
833	{
834		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,	// VkStructureType		sType;
835		DE_NULL,									// const void*			pNext;
836		VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,		// VkCmdPoolCreateFlags	flags;
837		queueFamilyIndex,							// deUint32				queueFamilyIndex;
838	};
839
840	Move<VkCommandPool>					cmdPool				= createCommandPool(vk, vkDevice, &cmdPoolParams);
841
842	// Create command buffer
843	const VkCommandBufferAllocateInfo	cmdBufferParams		=
844	{
845		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
846		DE_NULL,										// const void*				pNext;
847		*cmdPool,										// VkCommandPool			commandPool;
848		VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
849		1u												// deUint32					bufferCount;
850	};
851
852	const VkCommandBufferUsageFlags		usageFlags			= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
853	const VkCommandBufferBeginInfo		cmdBufferBeginInfo	=
854	{
855		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType				sType;
856		DE_NULL,										// const void*					pNext;
857		usageFlags,										// VkCommandBufferUsageFlags	flags;
858		(const VkCommandBufferInheritanceInfo*)DE_NULL,
859	};
860
861	Move<VkCommandBuffer>				cmdBuffer			= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
862
863	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
864
865	// Add image barriers
866	const VkImageMemoryBarrier			layoutBarriers[2]	=
867	{
868		createImageMemoryBarrier(srcImage, (VkAccessFlags)0u, (VkAccessFlags)0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
869		createImageMemoryBarrier(dstImage, (VkAccessFlags)0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
870	};
871
872	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
873						  0, (const VkMemoryBarrier*)DE_NULL,
874						  0, (const VkBufferMemoryBarrier*)DE_NULL,
875						  DE_LENGTH_OF_ARRAY(layoutBarriers), layoutBarriers);
876
877	// Add image copy
878	const VkImageCopy				imageCopy			=
879	{
880		{
881			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspect	aspect;
882			0u,								// deUint32			mipLevel;
883			0u,								// deUint32			arrayLayer;
884			1u								// deUint32			arraySize;
885		},											// VkImageSubresourceCopy	srcSubresource;
886		{
887			0,								// int32			x;
888			0,								// int32			y;
889			0								// int32			z;
890		},											// VkOffset3D				srcOffset;
891		{
892			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspect	aspect;
893			0u,								// deUint32			mipLevel;
894			0u,								// deUint32			arrayLayer;
895			1u								// deUint32			arraySize;
896		},											// VkImageSubresourceCopy	destSubResource;
897		{
898			0,								// int32			x;
899			0,								// int32			y;
900			0								// int32			z;
901		},											// VkOffset3D				dstOffset;
902		{
903			width,							// int32			width;
904			height,							// int32			height;
905			1,								// int32			depth
906		}	// VkExtent3D					extent;
907	};
908
909	vk.cmdCopyImage(*cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy);
910
911	// Add destination barrier
912	const VkImageMemoryBarrier		dstBarrier			=
913			createImageMemoryBarrier(dstImage, VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, 0u, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
914
915	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
916						  0, (const VkMemoryBarrier*)DE_NULL,
917						  0, (const VkBufferMemoryBarrier*)DE_NULL,
918						  1, &dstBarrier);
919
920	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
921
922	const VkFenceCreateInfo			fenceParams			=
923	{
924		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
925		DE_NULL,								// const void*			pNext;
926		0u										// VkFenceCreateFlags	flags;
927	};
928	const Unique<VkFence>			fence				(createFence(vk, vkDevice, &fenceParams));
929	const VkSubmitInfo				submitInfo			=
930	{
931		VK_STRUCTURE_TYPE_SUBMIT_INFO,
932		DE_NULL,
933		0u,
934		(const VkSemaphore*)DE_NULL,
935		(const VkPipelineStageFlags*)DE_NULL,
936		1u,
937		&cmdBuffer.get(),
938		0u,
939		(const VkSemaphore*)DE_NULL,
940	};
941
942
943	// Execute copy
944	VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
945	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
946	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
947}
948
949void ShaderRenderCaseInstance::useSampler2D (deUint32 bindingLocation, deUint32 textureID)
950{
951	DE_ASSERT(textureID < m_textures.size());
952
953	const VkDevice					vkDevice		= m_context.getDevice();
954	const DeviceInterface&			vk				= m_context.getDeviceInterface();
955	const TextureBinding&			textureBinding	= *m_textures[textureID];
956	const tcu::Texture2D&			refTexture		= textureBinding.get2D();
957	const tcu::Sampler&				refSampler		= textureBinding.getSampler();
958	const VkFormat					format			= refTexture.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
959														? VK_FORMAT_R8G8B8A8_UNORM
960														: VK_FORMAT_R8G8B8_UNORM;
961
962	// Create & alloc the image
963	Move<VkImage>					vkTexture;
964	de::MovePtr<Allocation>			allocation;
965
966	if (isSupportedLinearTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
967	{
968		vkTexture = createImage2D(refTexture, format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_LINEAR);
969		allocation = uploadImage2D(refTexture, *vkTexture);
970	}
971	else if (isSupportedOptimalTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
972	{
973		Move<VkImage>				stagingTexture	(createImage2D(refTexture, format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR));
974		de::MovePtr<Allocation>		stagingAlloc	(uploadImage2D(refTexture, *stagingTexture));
975
976		const VkImageUsageFlags		dstUsageFlags	= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
977		vkTexture = createImage2D(refTexture, format, dstUsageFlags, VK_IMAGE_TILING_OPTIMAL);
978		allocation = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
979		VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
980
981		copyTilingImageToOptimal(*stagingTexture, *vkTexture, refTexture.getWidth(), refTexture.getHeight());
982	}
983	else
984	{
985		TCU_THROW(InternalError, "Unable to create 2D image");
986	}
987
988	// Create sampler
989	const VkSamplerCreateInfo		samplerParams	= mapSampler(refSampler, refTexture.getFormat());
990	Move<VkSampler>					sampler			= createSampler(vk, vkDevice, &samplerParams);
991
992	const VkImageViewCreateInfo		viewParams		=
993	{
994		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
995		NULL,										// const voide*				pNext;
996		0u,											// VkImageViewCreateFlags	flags;
997		*vkTexture,									// VkImage					image;
998		VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
999		format,										// VkFormat					format;
1000		{
1001			VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
1002			VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
1003			VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
1004			VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
1005		},											// VkChannelMapping			channels;
1006		{
1007			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
1008			0,								// deUint32				baseMipLevel;
1009			1,								// deUint32				mipLevels;
1010			0,								// deUint32				baseArraySlice;
1011			1								// deUint32				arraySize;
1012		},											// VkImageSubresourceRange	subresourceRange;
1013	};
1014
1015	Move<VkImageView>				imageView		= createImageView(vk, vkDevice, &viewParams);
1016
1017	const vk::VkDescriptorImageInfo	descriptor		=
1018	{
1019		sampler.get(),								// VkSampler				sampler;
1020		imageView.get(),							// VkImageView				imageView;
1021		VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			imageLayout;
1022	};
1023
1024	de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
1025	uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1026	uniform->descriptor = descriptor;
1027	uniform->location = bindingLocation;
1028	uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
1029	uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
1030	uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
1031	uniform->alloc = AllocationSp(allocation.release());
1032
1033	m_descriptorSetLayoutBuilder.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_ALL, &uniform->descriptor.sampler);
1034	m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1035
1036	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
1037}
1038
1039void ShaderRenderCaseInstance::setupDefaultInputs (const QuadGrid& quadGrid)
1040{
1041	/* Configuration of the vertex input attributes:
1042		a_position   is at location 0
1043		a_coords     is at location 1
1044		a_unitCoords is at location 2
1045		a_one        is at location 3
1046
1047	  User attributes starts from at the location 4.
1048	*/
1049	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
1050	addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
1051	addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
1052	addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
1053
1054	static const struct
1055	{
1056		BaseAttributeType	type;
1057		int					userNdx;
1058	} userAttributes[] =
1059	{
1060		{ A_IN0, 0 },
1061		{ A_IN1, 1 },
1062		{ A_IN2, 2 },
1063		{ A_IN3, 3 }
1064	};
1065
1066	static const struct
1067	{
1068		BaseAttributeType	matrixType;
1069		int					numCols;
1070		int					numRows;
1071	} matrices[] =
1072	{
1073		{ MAT2,		2, 2 },
1074		{ MAT2x3,	2, 3 },
1075		{ MAT2x4,	2, 4 },
1076		{ MAT3x2,	3, 2 },
1077		{ MAT3,		3, 3 },
1078		{ MAT3x4,	3, 4 },
1079		{ MAT4x2,	4, 2 },
1080		{ MAT4x3,	4, 3 },
1081		{ MAT4,		4, 4 }
1082	};
1083
1084	for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
1085	{
1086		for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
1087		{
1088			if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
1089				continue;
1090
1091			addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
1092		}
1093
1094		for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
1095		{
1096
1097			if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
1098				continue;
1099
1100			const int numCols = matrices[matNdx].numCols;
1101
1102			for (int colNdx = 0; colNdx < numCols; colNdx++)
1103			{
1104				addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(4 * sizeof(float)), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
1105			}
1106		}
1107	}
1108}
1109
1110void ShaderRenderCaseInstance::render (tcu::Surface& result, const QuadGrid& quadGrid)
1111{
1112	const VkDevice										vkDevice					= m_context.getDevice();
1113	const DeviceInterface&								vk							= m_context.getDeviceInterface();
1114	const VkQueue										queue						= m_context.getUniversalQueue();
1115	const deUint32										queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1116
1117	// Create color image
1118	{
1119		const VkImageCreateInfo							colorImageParams			=
1120		{
1121			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType		sType;
1122			DE_NULL,																	// const void*			pNext;
1123			0u,																			// VkImageCreateFlags	flags;
1124			VK_IMAGE_TYPE_2D,															// VkImageType			imageType;
1125			m_colorFormat,																// VkFormat				format;
1126			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D			extent;
1127			1u,																			// deUint32				mipLevels;
1128			1u,																			// deUint32				arraySize;
1129			VK_SAMPLE_COUNT_1_BIT,														// deUint32				samples;
1130			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling		tiling;
1131			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags	usage;
1132			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode;
1133			1u,																			// deUint32				queueFamilyCount;
1134			&queueFamilyIndex,															// const deUint32*		pQueueFamilyIndices;
1135			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout		initialLayout;
1136		};
1137
1138		m_colorImage = createImage(vk, vkDevice, &colorImageParams);
1139
1140		// Allocate and bind color image memory
1141		m_colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1142		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1143	}
1144
1145	// Create color attachment view
1146	{
1147		const VkImageViewCreateInfo						colorImageViewParams		=
1148		{
1149			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1150			DE_NULL,											// const void*				pNext;
1151			0u,													// VkImageViewCreateFlags	flags;
1152			*m_colorImage,										// VkImage					image;
1153			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1154			m_colorFormat,										// VkFormat					format;
1155			{
1156				VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
1157				VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
1158				VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
1159				VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
1160			},													// VkChannelMapping			channels;
1161			{
1162				VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
1163				0,								// deUint32				baseMipLevel;
1164				1,								// deUint32				mipLevels;
1165				0,								// deUint32				baseArraySlice;
1166				1								// deUint32				arraySize;
1167			},													// VkImageSubresourceRange	subresourceRange;
1168		};
1169
1170		m_colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
1171	}
1172
1173	// Create render pass
1174	{
1175		const VkAttachmentDescription					attachmentDescription		=
1176		{
1177			(VkAttachmentDescriptionFlags)0,
1178			m_colorFormat,										// VkFormat						format;
1179			VK_SAMPLE_COUNT_1_BIT,								// deUint32						samples;
1180			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			loadOp;
1181			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp			storeOp;
1182			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp			stencilLoadOp;
1183			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			stencilStoreOp;
1184			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				initialLayout;
1185			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				finalLayout;
1186		};
1187
1188		const VkAttachmentReference						attachmentReference			=
1189		{
1190			0u,													// deUint32			attachment;
1191			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1192		};
1193
1194		const VkSubpassDescription						subpassDescription			=
1195		{
1196			0u,													// VkSubpassDescriptionFlags	flags;
1197			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
1198			0u,													// deUint32						inputCount;
1199			DE_NULL,											// constVkAttachmentReference*	pInputAttachments;
1200			1u,													// deUint32						colorCount;
1201			&attachmentReference,								// constVkAttachmentReference*	pColorAttachments;
1202			DE_NULL,											// constVkAttachmentReference*	pResolveAttachments;
1203			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
1204			0u,													// deUint32						preserveCount;
1205			DE_NULL												// constVkAttachmentReference*	pPreserveAttachments;
1206		};
1207
1208		const VkRenderPassCreateInfo					renderPassParams			=
1209		{
1210			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
1211			DE_NULL,											// const void*						pNext;
1212			(VkRenderPassCreateFlags)0,
1213			1u,													// deUint32							attachmentCount;
1214			&attachmentDescription,								// const VkAttachmentDescription*	pAttachments;
1215			1u,													// deUint32							subpassCount;
1216			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
1217			0u,													// deUint32							dependencyCount;
1218			DE_NULL												// const VkSubpassDependency*		pDependencies;
1219		};
1220
1221		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
1222	}
1223
1224	// Create framebuffer
1225	{
1226		const VkFramebufferCreateInfo					framebufferParams			=
1227		{
1228			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
1229			DE_NULL,											// const void*					pNext;
1230			(VkFramebufferCreateFlags)0,
1231			*m_renderPass,										// VkRenderPass					renderPass;
1232			1u,													// deUint32						attachmentCount;
1233			&*m_colorImageView,									// const VkImageView*			pAttachments;
1234			(deUint32)m_renderSize.x(),							// deUint32						width;
1235			(deUint32)m_renderSize.y(),							// deUint32						height;
1236			1u													// deUint32						layers;
1237		};
1238
1239		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1240	}
1241
1242	// Create descriptors
1243	{
1244		setupUniforms(quadGrid.getConstCoords());
1245
1246		m_descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
1247		if (!m_uniformInfos.empty())
1248		{
1249			m_descriptorPool 								= m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1250			const VkDescriptorSetAllocateInfo	allocInfo	=
1251			{
1252				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1253				DE_NULL,
1254				*m_descriptorPool,
1255				1u,
1256				&m_descriptorSetLayout.get(),
1257			};
1258
1259			m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
1260		}
1261
1262		for (deUint32 i = 0; i < m_uniformInfos.size(); i++)
1263		{
1264			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1265			deUint32 location = uniformInfo->location;
1266
1267			if (uniformInfo->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
1268			{
1269				const BufferUniform*	bufferInfo	= dynamic_cast<const BufferUniform*>(uniformInfo);
1270
1271				m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &bufferInfo->descriptor);
1272			}
1273			else if (uniformInfo->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1274			{
1275				const SamplerUniform*	samplerInfo	= dynamic_cast<const SamplerUniform*>(uniformInfo);
1276
1277				m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &samplerInfo->descriptor);
1278			}
1279			else
1280				DE_FATAL("Impossible");
1281		}
1282
1283		m_descriptorSetUpdateBuilder.update(vk, vkDevice);
1284	}
1285
1286	// Create pipeline layout
1287	{
1288		const VkPipelineLayoutCreateInfo				pipelineLayoutParams		=
1289		{
1290			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1291			DE_NULL,											// const void*					pNext;
1292			(VkPipelineLayoutCreateFlags)0,
1293			1u,													// deUint32						descriptorSetCount;
1294			&*m_descriptorSetLayout,							// const VkDescriptorSetLayout*	pSetLayouts;
1295			0u,													// deUint32						pushConstantRangeCount;
1296			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
1297		};
1298
1299		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1300	}
1301
1302	// Create shaders
1303	{
1304		m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
1305		m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
1306	}
1307
1308	// Create pipeline
1309	{
1310		const VkPipelineShaderStageCreateInfo			shaderStageParams[2]		=
1311		{
1312			{
1313				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
1314				DE_NULL,													// const void*					pNext;
1315				(VkPipelineShaderStageCreateFlags)0,
1316				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStage				stage;
1317				*m_vertexShaderModule,										// VkShader						shader;
1318				"main",
1319				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
1320			},
1321			{
1322				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
1323				DE_NULL,													// const void*					pNext;
1324				(VkPipelineShaderStageCreateFlags)0,
1325				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStage				stage;
1326				*m_fragmentShaderModule,									// VkShader						shader;
1327				"main",
1328				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
1329			}
1330		};
1331
1332		// Add test case specific attributes
1333		if (m_attribFunc)
1334			m_attribFunc(*this, quadGrid.getNumVertices());
1335
1336		// Add base attributes
1337		setupDefaultInputs(quadGrid);
1338
1339		const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams		=
1340		{
1341			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1342			DE_NULL,														// const void*								pNext;
1343			(VkPipelineVertexInputStateCreateFlags)0,
1344			(deUint32)m_vertexBindingDescription.size(),					// deUint32									bindingCount;
1345			&m_vertexBindingDescription[0],									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1346			(deUint32)m_vertexattributeDescription.size(),					// deUint32									attributeCount;
1347			&m_vertexattributeDescription[0],								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1348		};
1349
1350		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams	=
1351		{
1352			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType		sType;
1353			DE_NULL,														// const void*			pNext;
1354			(VkPipelineInputAssemblyStateCreateFlags)0,
1355			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology	topology;
1356			false															// VkBool32				primitiveRestartEnable;
1357		};
1358
1359		const VkViewport								viewport					=
1360		{
1361			0.0f,						// float	originX;
1362			0.0f,						// float	originY;
1363			(float)m_renderSize.x(),	// float	width;
1364			(float)m_renderSize.y(),	// float	height;
1365			0.0f,						// float	minDepth;
1366			1.0f						// float	maxDepth;
1367		};
1368
1369		const VkRect2D									scissor						=
1370		{
1371			{
1372				0u,					// deUint32	x;
1373				0u,					// deUint32	y;
1374			},							// VkOffset2D	offset;
1375			{
1376				m_renderSize.x(),	// deUint32	width;
1377				m_renderSize.y(),	// deUint32	height;
1378			},							// VkExtent2D	extent;
1379		};
1380
1381		const VkPipelineViewportStateCreateInfo			viewportStateParams			=
1382		{
1383			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType		sType;
1384			DE_NULL,														// const void*			pNext;
1385			(VkPipelineViewportStateCreateFlags)0,
1386			1u,																// deUint32				viewportCount;
1387			&viewport,														// const VkViewport*	pViewports;
1388			1u,																// deUint32				scissorsCount;
1389			&scissor,														// const VkRect2D*		pScissors;
1390		};
1391
1392		const VkPipelineRasterizationStateCreateInfo	rasterStateParams			=
1393		{
1394			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType	sType;
1395			DE_NULL,														// const void*		pNext;
1396			(VkPipelineRasterizationStateCreateFlags)0,
1397			false,															// VkBool32			depthClipEnable;
1398			false,															// VkBool32			rasterizerDiscardEnable;
1399			VK_POLYGON_MODE_FILL,											// VkFillMode		fillMode;
1400			VK_CULL_MODE_NONE,												// VkCullMode		cullMode;
1401			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace		frontFace;
1402			false,															// VkBool32			depthBiasEnable;
1403			0.0f,															// float			depthBias;
1404			0.0f,															// float			depthBiasClamp;
1405			0.0f,															// float			slopeScaledDepthBias;
1406			1.0f,															// float			lineWidth;
1407		};
1408
1409		const VkPipelineMultisampleStateCreateInfo		multisampleStateParams =
1410		{
1411			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
1412			DE_NULL,														// const void*								pNext;
1413			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
1414			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
1415			VK_FALSE,														// VkBool32									sampleShadingEnable;
1416			0.0f,															// float									minSampleShading;
1417			DE_NULL,														// const VkSampleMask*						pSampleMask;
1418			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
1419			VK_FALSE														// VkBool32									alphaToOneEnable;
1420		};
1421
1422		const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState	=
1423		{
1424			false,															// VkBool32			blendEnable;
1425			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendColor;
1426			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendColor;
1427			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpColor;
1428			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendAlpha;
1429			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendAlpha;
1430			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpAlpha;
1431			(VK_COLOR_COMPONENT_R_BIT |
1432			 VK_COLOR_COMPONENT_G_BIT |
1433			 VK_COLOR_COMPONENT_B_BIT |
1434			 VK_COLOR_COMPONENT_A_BIT),										// VkChannelFlags	channelWriteMask;
1435		};
1436
1437		const VkPipelineColorBlendStateCreateInfo		colorBlendStateParams		=
1438		{
1439			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1440			DE_NULL,													// const void*									pNext;
1441			(VkPipelineColorBlendStateCreateFlags)0,
1442			false,														// VkBool32										logicOpEnable;
1443			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1444			1u,															// deUint32										attachmentCount;
1445			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1446			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1447		};
1448
1449		const VkPipelineDynamicStateCreateInfo			dynamicStateInfo			=
1450		{
1451			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,		// VkStructureType				sType;
1452			DE_NULL,													// const void*					pNext;
1453			(VkPipelineDynamicStateCreateFlags)0,
1454			0u,															// deUint32						dynamicStateCount;
1455			DE_NULL														// const VkDynamicState*		pDynamicStates;
1456		};
1457
1458		const VkGraphicsPipelineCreateInfo				graphicsPipelineParams		=
1459		{
1460			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1461			DE_NULL,											// const void*										pNext;
1462			0u,													// VkPipelineCreateFlags							flags;
1463			2u,													// deUint32											stageCount;
1464			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
1465			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1466			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1467			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1468			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1469			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
1470			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1471			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1472			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1473			&dynamicStateInfo,									// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1474			*m_pipelineLayout,									// VkPipelineLayout									layout;
1475			*m_renderPass,										// VkRenderPass										renderPass;
1476			0u,													// deUint32											subpass;
1477			0u,													// VkPipeline										basePipelineHandle;
1478			0u													// deInt32											basePipelineIndex;
1479		};
1480
1481		m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1482	}
1483
1484	// Create vertex indices buffer
1485	{
1486		const VkDeviceSize								indiceBufferSize			= quadGrid.getNumTriangles() * 3 * sizeof(deUint16);
1487		const VkBufferCreateInfo						indiceBufferParams			=
1488		{
1489			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1490			DE_NULL,									// const void*			pNext;
1491			0u,											// VkBufferCreateFlags	flags;
1492			indiceBufferSize,							// VkDeviceSize			size;
1493			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1494			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1495			1u,											// deUint32				queueFamilyCount;
1496			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1497		};
1498
1499		m_indiceBuffer		= createBuffer(vk, vkDevice, &indiceBufferParams);
1500		m_indiceBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indiceBuffer), MemoryRequirement::HostVisible);
1501
1502		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indiceBuffer, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset()));
1503
1504		// Load vertice indices into buffer
1505		deMemcpy(m_indiceBufferAlloc->getHostPtr(), quadGrid.getIndices(), (size_t)indiceBufferSize);
1506		flushMappedMemoryRange(vk, vkDevice, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset(), indiceBufferSize);
1507	}
1508
1509	// Create command pool
1510	{
1511		const VkCommandPoolCreateInfo					cmdPoolParams				=
1512		{
1513			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType		sType;
1514			DE_NULL,										// const void*			pNext;
1515			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCmdPoolCreateFlags	flags;
1516			queueFamilyIndex,								// deUint32				queueFamilyIndex;
1517		};
1518
1519		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1520	}
1521
1522	// Create command buffer
1523	{
1524		const VkCommandBufferAllocateInfo				cmdBufferParams				=
1525		{
1526			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1527			DE_NULL,										// const void*				pNext;
1528			*m_cmdPool,										// VkCmdPool				cmdPool;
1529			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
1530			1u												// deUint32					bufferCount;
1531		};
1532
1533		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
1534		{
1535			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
1536			DE_NULL,										// const void*				pNext;
1537			0u,												// VkCmdBufferOptimizeFlags	flags;
1538			(const VkCommandBufferInheritanceInfo*)DE_NULL,
1539		};
1540
1541		const VkClearValue								clearValues					= makeClearValueColorF32(m_clearColor.x(),
1542																											 m_clearColor.y(),
1543																											 m_clearColor.z(),
1544																											 m_clearColor.w());
1545
1546		const VkRenderPassBeginInfo						renderPassBeginInfo			=
1547		{
1548			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
1549			DE_NULL,												// const void*			pNext;
1550			*m_renderPass,											// VkRenderPass			renderPass;
1551			*m_framebuffer,											// VkFramebuffer		framebuffer;
1552			{ { 0, 0 },  {m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
1553			1,														// deUint32				clearValueCount;
1554			&clearValues,											// const VkClearValue*	pClearValues;
1555		};
1556
1557		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1558
1559		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1560
1561		// Add texture barriers
1562		std::vector<VkImageMemoryBarrier> barriers;
1563
1564		for(deUint32 i = 0; i < m_uniformInfos.size(); i++)
1565		{
1566			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1567
1568			if (uniformInfo->type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1569			{
1570				continue;
1571			}
1572
1573			const SamplerUniform*		sampler			= static_cast<const SamplerUniform*>(uniformInfo);
1574
1575			const VkAccessFlags			outputMask		= VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
1576			const VkImageMemoryBarrier	textureBarrier	= createImageMemoryBarrier(sampler->image->get(), outputMask, 0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1577
1578			barriers.push_back(textureBarrier);
1579		}
1580
1581		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
1582							  0, (const VkMemoryBarrier*)DE_NULL,
1583							  0, (const VkBufferMemoryBarrier*)DE_NULL,
1584							  (deUint32)barriers.size(), (barriers.empty() ? (const VkImageMemoryBarrier*)DE_NULL : &barriers[0]));
1585
1586		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1587
1588		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1589		if (!m_uniformInfos.empty())
1590			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &*m_descriptorSet, 0u, DE_NULL);
1591		vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indiceBuffer, 0, VK_INDEX_TYPE_UINT16);
1592
1593		const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
1594		const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
1595
1596		std::vector<VkBuffer> buffers(numberOfVertexAttributes);
1597		for (size_t i = 0; i < numberOfVertexAttributes; i++)
1598		{
1599			buffers[i] = m_vertexBuffers[i].get()->get();
1600		}
1601
1602		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
1603		vk.cmdDrawIndexed(*m_cmdBuffer, quadGrid.getNumTriangles() * 3, 1, 0, 0, 0);
1604
1605		vk.cmdEndRenderPass(*m_cmdBuffer);
1606		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1607	}
1608
1609	// Create fence
1610	{
1611		const VkFenceCreateInfo							fenceParams					=
1612		{
1613			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
1614			DE_NULL,								// const void*			pNext;
1615			0u										// VkFenceCreateFlags	flags;
1616		};
1617		m_fence = createFence(vk, vkDevice, &fenceParams);
1618	}
1619
1620	// Execute Draw
1621	{
1622		const VkSubmitInfo	submitInfo	=
1623		{
1624			VK_STRUCTURE_TYPE_SUBMIT_INFO,
1625			DE_NULL,
1626			0u,
1627			(const VkSemaphore*)DE_NULL,
1628			(const VkPipelineStageFlags*)DE_NULL,
1629			1u,
1630			&m_cmdBuffer.get(),
1631			0u,
1632			(const VkSemaphore*)DE_NULL,
1633		};
1634
1635		VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1636		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1637		VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1638	}
1639
1640	// Read back the result
1641	{
1642		const VkDeviceSize								imageSizeBytes				= (VkDeviceSize)(sizeof(deUint32) * m_renderSize.x() * m_renderSize.y());
1643		const VkBufferCreateInfo						readImageBufferParams		=
1644		{
1645			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//  VkStructureType		sType;
1646			DE_NULL,									//  const void*			pNext;
1647			0u,											//  VkBufferCreateFlags	flags;
1648			imageSizeBytes,								//  VkDeviceSize		size;
1649			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//  VkBufferUsageFlags	usage;
1650			VK_SHARING_MODE_EXCLUSIVE,					//  VkSharingMode		sharingMode;
1651			1u,											//  deUint32			queueFamilyCount;
1652			&queueFamilyIndex,							//  const deUint32*		pQueueFamilyIndices;
1653		};
1654		const Unique<VkBuffer>							readImageBuffer				(createBuffer(vk, vkDevice, &readImageBufferParams));
1655		const de::UniquePtr<Allocation>					readImageBufferMemory		(m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
1656
1657		VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
1658
1659		// Copy image to buffer
1660		const VkCommandBufferAllocateInfo				cmdBufferParams				=
1661		{
1662			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1663			DE_NULL,										// const void*				pNext;
1664			*m_cmdPool,										// VkCmdPool				cmdPool;
1665			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
1666			1u												// deUint32					bufferCount;
1667		};
1668
1669		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
1670		{
1671			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
1672			DE_NULL,										// const void*				pNext;
1673			0u,												// VkCmdBufferOptimizeFlags	flags;
1674			(const VkCommandBufferInheritanceInfo*)DE_NULL,
1675		};
1676
1677		const Move<VkCommandBuffer>						cmdBuffer					= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1678
1679		const VkBufferImageCopy							copyParams					=
1680		{
1681			0u,											// VkDeviceSize			bufferOffset;
1682			(deUint32)m_renderSize.x(),					// deUint32				bufferRowLength;
1683			(deUint32)m_renderSize.y(),					// deUint32				bufferImageHeight;
1684			{
1685				VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspect		aspect;
1686				0u,									// deUint32				mipLevel;
1687				0u,									// deUint32				arraySlice;
1688				1u,									// deUint32				arraySize;
1689			},											// VkImageSubresourceCopy	imageSubresource;
1690			{ 0u, 0u, 0u },								// VkOffset3D			imageOffset;
1691			{ m_renderSize.x(), m_renderSize.y(), 1u }	// VkExtent3D			imageExtent;
1692		};
1693		const VkSubmitInfo								submitInfo					=
1694		{
1695			VK_STRUCTURE_TYPE_SUBMIT_INFO,
1696			DE_NULL,
1697			0u,
1698			(const VkSemaphore*)DE_NULL,
1699			(const VkPipelineStageFlags*)DE_NULL,
1700			1u,
1701			&cmdBuffer.get(),
1702			0u,
1703			(const VkSemaphore*)DE_NULL,
1704		};
1705
1706		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1707		vk.cmdCopyImageToBuffer(*cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
1708		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1709
1710		VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1711		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1712		VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1713
1714		invalidateMappedMemoryRange(vk, vkDevice, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset(), imageSizeBytes);
1715
1716		const tcu::TextureFormat						resultFormat				(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1717		const tcu::ConstPixelBufferAccess				resultAccess				(resultFormat, m_renderSize.x(), m_renderSize.y(), 1, readImageBufferMemory->getHostPtr());
1718
1719		tcu::copy(result.getAccess(), resultAccess);
1720	}
1721}
1722
1723void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
1724{
1725	// Buffer info.
1726	const int				width		= result.getWidth();
1727	const int				height		= result.getHeight();
1728	const int				gridSize	= quadGrid.getGridSize();
1729	const int				stride		= gridSize + 1;
1730	const bool				hasAlpha	= true; // \todo [2015-09-07 elecro] add correct alpha check
1731	ShaderEvalContext		evalCtx		(quadGrid);
1732
1733	// Evaluate color for each vertex.
1734	std::vector<tcu::Vec4>	colors		((gridSize + 1) * (gridSize + 1));
1735	for (int y = 0; y < gridSize+1; y++)
1736	for (int x = 0; x < gridSize+1; x++)
1737	{
1738		const float	sx			= (float)x / (float)gridSize;
1739		const float	sy			= (float)y / (float)gridSize;
1740		const int	vtxNdx		= ((y * (gridSize+1)) + x);
1741
1742		evalCtx.reset(sx, sy);
1743		m_evaluator.evaluate(evalCtx);
1744		DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
1745		tcu::Vec4 color = evalCtx.color;
1746
1747		if (!hasAlpha)
1748			color.w() = 1.0f;
1749
1750		colors[vtxNdx] = color;
1751	}
1752
1753	// Render quads.
1754	for (int y = 0; y < gridSize; y++)
1755	for (int x = 0; x < gridSize; x++)
1756	{
1757		const float		x0		= (float)x       / (float)gridSize;
1758		const float		x1		= (float)(x + 1) / (float)gridSize;
1759		const float		y0		= (float)y       / (float)gridSize;
1760		const float		y1		= (float)(y + 1) / (float)gridSize;
1761
1762		const float		sx0		= x0 * (float)width;
1763		const float		sx1		= x1 * (float)width;
1764		const float		sy0		= y0 * (float)height;
1765		const float		sy1		= y1 * (float)height;
1766		const float		oosx	= 1.0f / (sx1 - sx0);
1767		const float		oosy	= 1.0f / (sy1 - sy0);
1768
1769		const int		ix0		= deCeilFloatToInt32(sx0 - 0.5f);
1770		const int		ix1		= deCeilFloatToInt32(sx1 - 0.5f);
1771		const int		iy0		= deCeilFloatToInt32(sy0 - 0.5f);
1772		const int		iy1		= deCeilFloatToInt32(sy1 - 0.5f);
1773
1774		const int		v00		= (y * stride) + x;
1775		const int		v01		= (y * stride) + x + 1;
1776		const int		v10		= ((y + 1) * stride) + x;
1777		const int		v11		= ((y + 1) * stride) + x + 1;
1778		const tcu::Vec4	c00		= colors[v00];
1779		const tcu::Vec4	c01		= colors[v01];
1780		const tcu::Vec4	c10		= colors[v10];
1781		const tcu::Vec4	c11		= colors[v11];
1782
1783		//printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
1784
1785		for (int iy = iy0; iy < iy1; iy++)
1786		for (int ix = ix0; ix < ix1; ix++)
1787		{
1788			DE_ASSERT(deInBounds32(ix, 0, width));
1789			DE_ASSERT(deInBounds32(iy, 0, height));
1790
1791			const float			sfx		= (float)ix + 0.5f;
1792			const float			sfy		= (float)iy + 0.5f;
1793			const float			fx1		= deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
1794			const float			fy1		= deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
1795
1796			// Triangle quad interpolation.
1797			const bool			tri		= fx1 + fy1 <= 1.0f;
1798			const float			tx		= tri ? fx1 : (1.0f-fx1);
1799			const float			ty		= tri ? fy1 : (1.0f-fy1);
1800			const tcu::Vec4&	t0		= tri ? c00 : c11;
1801			const tcu::Vec4&	t1		= tri ? c01 : c10;
1802			const tcu::Vec4&	t2		= tri ? c10 : c01;
1803			const tcu::Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
1804
1805			result.setPixel(ix, iy, tcu::RGBA(color));
1806		}
1807	}
1808}
1809
1810void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
1811{
1812	// Buffer info.
1813	const int			width		= result.getWidth();
1814	const int			height		= result.getHeight();
1815	const bool			hasAlpha	= true;  // \todo [2015-09-07 elecro] add correct alpha check
1816	ShaderEvalContext	evalCtx		(quadGrid);
1817
1818	// Render.
1819	for (int y = 0; y < height; y++)
1820	for (int x = 0; x < width; x++)
1821	{
1822		const float sx = ((float)x + 0.5f) / (float)width;
1823		const float sy = ((float)y + 0.5f) / (float)height;
1824
1825		evalCtx.reset(sx, sy);
1826		m_evaluator.evaluate(evalCtx);
1827		// Select either clear color or computed color based on discarded bit.
1828		tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
1829
1830		if (!hasAlpha)
1831			color.w() = 1.0f;
1832
1833		result.setPixel(x, y, tcu::RGBA(color));
1834	}
1835}
1836
1837bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
1838{
1839	return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_RESULT);
1840}
1841
1842} // sr
1843} // vkt
1844