vktShaderRender.cpp revision 94128dffb454628346f09bb736e0f4ace9df0b9e
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		s_gridSize			= 2;
72static const int		s_maxRenderWidth	= 128;
73static const int		s_maxRenderHeight	= 128;
74static const tcu::Vec4	s_defaultClearColor	= 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		(s_defaultClearColor)
475	, m_memAlloc		(context.getDefaultAllocator())
476	, m_isVertexCase	(isVertexCase)
477	, m_evaluator		(evaluator)
478	, m_uniformSetup	(uniformSetup)
479	, m_attribFunc		(attribFunc)
480	, m_renderSize		(100, 100)
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::IVec2	viewportSize	= getViewportSize();
495	const int			width			= viewportSize.x();
496	const int			height			= viewportSize.y();
497
498	QuadGrid			quadGrid		(m_isVertexCase ? s_gridSize : 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, deUint32 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	// \todo [2015-10-09 elecro] remove the 'hackPadding' variable if the driver support small uniforms,
546	// that is for example one float big uniforms.
547	const deUint32 hackPadding = size < 4 * sizeof(float) ? (deUint32)(3u * sizeof(float)) : 0u;
548
549	de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
550	uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
551	uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size + hackPadding);
552	uniformInfo->location = bindingLocation;
553	uniformInfo->buffer = VkBufferSp(new vk::Unique<VkBuffer>(buffer));
554	uniformInfo->alloc = AllocationSp(alloc.release());
555
556	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
557}
558
559void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, deUint32 dataSize, const void* data)
560{
561	m_descriptorSetLayoutBuilder.addSingleBinding(descriptorType, vk::VK_SHADER_STAGE_ALL);
562	m_descriptorPoolBuilder.addType(descriptorType);
563
564	setupUniformData(bindingLocation, dataSize, data);
565}
566
567void ShaderRenderCaseInstance::addAttribute (deUint32		bindingLocation,
568											 vk::VkFormat	format,
569											 deUint32		sizePerElement,
570											 deUint32		count,
571											 const void*	dataPtr)
572{
573	// Add binding specification
574	const deUint32							binding					= (deUint32)m_vertexBindingDescription.size();
575	const VkVertexInputBindingDescription	bindingDescription		=
576	{
577		binding,							// deUint32				binding;
578		sizePerElement,						// deUint32				stride;
579		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	stepRate;
580	};
581
582	m_vertexBindingDescription.push_back(bindingDescription);
583
584	// Add location and format specification
585	const VkVertexInputAttributeDescription	attributeDescription	=
586	{
587		bindingLocation,			// deUint32	location;
588		binding,					// deUint32	binding;
589		format,						// VkFormat	format;
590		0u,							// deUint32	offset;
591	};
592
593	m_vertexattributeDescription.push_back(attributeDescription);
594
595	// Upload data to buffer
596	const VkDevice							vkDevice				= m_context.getDevice();
597	const DeviceInterface&					vk						= m_context.getDeviceInterface();
598	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
599
600	const VkDeviceSize						inputSize				= sizePerElement * count;
601	const VkBufferCreateInfo				vertexBufferParams		=
602	{
603		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
604		DE_NULL,									// const void*			pNext;
605		0u,											// VkBufferCreateFlags	flags;
606		inputSize,									// VkDeviceSize			size;
607		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
608		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
609		1u,											// deUint32				queueFamilyCount;
610		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
611	};
612
613	Move<VkBuffer>							buffer					= createBuffer(vk, vkDevice, &vertexBufferParams);
614	de::MovePtr<vk::Allocation>				alloc					= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
615	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
616
617	deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
618	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize);
619
620	m_vertexBuffers.push_back(VkBufferSp(new vk::Unique<VkBuffer>(buffer)));
621	m_vertexBufferAllocs.push_back(AllocationSp(alloc.release()));
622}
623
624void ShaderRenderCaseInstance::useAttribute (deUint32 bindingLocation, BaseAttributeType type)
625{
626	const EnabledBaseAttribute attribute =
627	{
628		bindingLocation,	// deUint32				location;
629		type				// BaseAttributeType	type;
630	};
631	m_enabledBaseAttributes.push_back(attribute);
632}
633
634void ShaderRenderCaseInstance::setup (void)
635{
636}
637
638void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
639{
640	m_uniformSetup.setup(*this, constCoords);
641}
642
643void ShaderRenderCaseInstance::useUniform (deUint32 bindingLocation, BaseUniformType type)
644{
645	#define UNIFORM_CASE(type, value) case type: addUniform(bindingLocation, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, value); break
646
647	switch(type)
648	{
649		// Bool
650		UNIFORM_CASE(UB_FALSE,	0);
651		UNIFORM_CASE(UB_TRUE,	1);
652
653		// BVec4
654		UNIFORM_CASE(UB4_FALSE,	tcu::Vec4(0));
655		UNIFORM_CASE(UB4_TRUE,	tcu::Vec4(1));
656
657		// Integer
658		UNIFORM_CASE(UI_ZERO,	0);
659		UNIFORM_CASE(UI_ONE,	1);
660		UNIFORM_CASE(UI_TWO,	2);
661		UNIFORM_CASE(UI_THREE,	3);
662		UNIFORM_CASE(UI_FOUR,	4);
663		UNIFORM_CASE(UI_FIVE,	5);
664		UNIFORM_CASE(UI_SIX,	6);
665		UNIFORM_CASE(UI_SEVEN,	7);
666		UNIFORM_CASE(UI_EIGHT,	8);
667		UNIFORM_CASE(UI_ONEHUNDREDONE, 101);
668
669		// IVec2
670		UNIFORM_CASE(UI2_MINUS_ONE,	tcu::IVec2(-1));
671		UNIFORM_CASE(UI2_ZERO,		tcu::IVec2(0));
672		UNIFORM_CASE(UI2_ONE,		tcu::IVec2(1));
673		UNIFORM_CASE(UI2_TWO,		tcu::IVec2(2));
674		UNIFORM_CASE(UI2_THREE,		tcu::IVec2(3));
675		UNIFORM_CASE(UI2_FOUR,		tcu::IVec2(4));
676		UNIFORM_CASE(UI2_FIVE,		tcu::IVec2(5));
677
678		// IVec3
679		UNIFORM_CASE(UI3_MINUS_ONE,	tcu::IVec3(-1));
680		UNIFORM_CASE(UI3_ZERO,		tcu::IVec3(0));
681		UNIFORM_CASE(UI3_ONE,		tcu::IVec3(1));
682		UNIFORM_CASE(UI3_TWO,		tcu::IVec3(2));
683		UNIFORM_CASE(UI3_THREE,		tcu::IVec3(3));
684		UNIFORM_CASE(UI3_FOUR,		tcu::IVec3(4));
685		UNIFORM_CASE(UI3_FIVE,		tcu::IVec3(5));
686
687		// IVec4
688		UNIFORM_CASE(UI4_MINUS_ONE, tcu::IVec4(-1));
689		UNIFORM_CASE(UI4_ZERO,		tcu::IVec4(0));
690		UNIFORM_CASE(UI4_ONE,		tcu::IVec4(1));
691		UNIFORM_CASE(UI4_TWO,		tcu::IVec4(2));
692		UNIFORM_CASE(UI4_THREE,		tcu::IVec4(3));
693		UNIFORM_CASE(UI4_FOUR,		tcu::IVec4(4));
694		UNIFORM_CASE(UI4_FIVE,		tcu::IVec4(5));
695
696		// Float
697		UNIFORM_CASE(UF_ZERO,		0.0f);
698		UNIFORM_CASE(UF_ONE,		1.0f);
699		UNIFORM_CASE(UF_TWO,		2.0f);
700		UNIFORM_CASE(UF_THREE,		3.0f);
701		UNIFORM_CASE(UF_FOUR,		4.0f);
702		UNIFORM_CASE(UF_FIVE,		5.0f);
703		UNIFORM_CASE(UF_SIX,		6.0f);
704		UNIFORM_CASE(UF_SEVEN,		7.0f);
705		UNIFORM_CASE(UF_EIGHT,		8.0f);
706
707		UNIFORM_CASE(UF_HALF,		1.0f / 2.0f);
708		UNIFORM_CASE(UF_THIRD,		1.0f / 3.0f);
709		UNIFORM_CASE(UF_FOURTH,		1.0f / 4.0f);
710		UNIFORM_CASE(UF_FIFTH,		1.0f / 5.0f);
711		UNIFORM_CASE(UF_SIXTH,		1.0f / 6.0f);
712		UNIFORM_CASE(UF_SEVENTH,	1.0f / 7.0f);
713		UNIFORM_CASE(UF_EIGHTH,		1.0f / 8.0f);
714
715		// Vec2
716		UNIFORM_CASE(UV2_MINUS_ONE,	tcu::Vec2(-1.0f));
717		UNIFORM_CASE(UV2_ZERO,		tcu::Vec2(0.0f));
718		UNIFORM_CASE(UV2_ONE,		tcu::Vec2(1.0f));
719		UNIFORM_CASE(UV2_TWO,		tcu::Vec2(2.0f));
720		UNIFORM_CASE(UV2_THREE,		tcu::Vec2(3.0f));
721
722		UNIFORM_CASE(UV2_HALF,		tcu::Vec2(1.0f / 2.0f));
723
724		// Vec3
725		UNIFORM_CASE(UV3_MINUS_ONE,	tcu::Vec3(-1.0f));
726		UNIFORM_CASE(UV3_ZERO,		tcu::Vec3(0.0f));
727		UNIFORM_CASE(UV3_ONE,		tcu::Vec3(1.0f));
728		UNIFORM_CASE(UV3_TWO,		tcu::Vec3(2.0f));
729		UNIFORM_CASE(UV3_THREE,		tcu::Vec3(3.0f));
730
731		UNIFORM_CASE(UV3_HALF,		tcu::Vec3(1.0f / 2.0f));
732
733		// Vec4
734		UNIFORM_CASE(UV4_MINUS_ONE,	tcu::Vec4(-1.0f));
735		UNIFORM_CASE(UV4_ZERO,		tcu::Vec4(0.0f));
736		UNIFORM_CASE(UV4_ONE,		tcu::Vec4(1.0f));
737		UNIFORM_CASE(UV4_TWO,		tcu::Vec4(2.0f));
738		UNIFORM_CASE(UV4_THREE,		tcu::Vec4(3.0f));
739
740		UNIFORM_CASE(UV4_HALF,		tcu::Vec4(1.0f / 2.0f));
741
742		UNIFORM_CASE(UV4_BLACK,		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
743		UNIFORM_CASE(UV4_GRAY,		tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
744		UNIFORM_CASE(UV4_WHITE,		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
745
746		default:
747			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unknown Uniform type: " << type << tcu::TestLog::EndMessage;
748			break;
749	}
750
751	#undef UNIFORM_CASE
752}
753
754const tcu::IVec2 ShaderRenderCaseInstance::getViewportSize (void) const
755{
756	return tcu::IVec2(de::min(m_renderSize.x(), s_maxRenderWidth),
757					  de::min(m_renderSize.y(), s_maxRenderHeight));
758}
759
760Move<VkImage> ShaderRenderCaseInstance::createImage2D (const tcu::Texture2D&	texture,
761													   const VkFormat			format,
762													   const VkImageUsageFlags	usage,
763													   const VkImageTiling		tiling)
764{
765	const VkDevice			vkDevice			= m_context.getDevice();
766	const DeviceInterface&	vk					= m_context.getDeviceInterface();
767	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
768
769	const VkImageCreateInfo	imageCreateInfo		=
770	{
771		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,						// VkStructureType			sType;
772		DE_NULL,													// const void*				pNext;
773		0,															// VkImageCreateFlags		flags;
774		VK_IMAGE_TYPE_2D,											// VkImageType				imageType;
775		format,														// VkFormat					format;
776		{ texture.getWidth(), texture.getHeight(), 1 },				// 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, layout.size);
817
818	return allocation;
819}
820
821void ShaderRenderCaseInstance::copyTilingImageToOptimal	(const vk::VkImage&	srcImage,
822														 const vk::VkImage&	dstImage,
823														 deInt32 width,
824														 deInt32 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		0u												// 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		DE_NULL,										// VkRenderPass					renderPass;
859		0u,												// deUint32						subpass;
860		DE_NULL,										// VkFramebuffer				framebuffer;
861		VK_FALSE,										// VkBool32						occlusionQueryEnable;
862		(VkQueryControlFlags)0,
863		(VkQueryPipelineStatisticFlags)0,
864	};
865
866	Move<VkCommandBuffer>				cmdBuffer			= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
867
868	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
869
870	// Add image barriers
871	const VkImageMemoryBarrier			layoutBarriers[2]	=
872	{
873		createImageMemoryBarrier(srcImage, (VkAccessFlags)0u, (VkAccessFlags)0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
874		createImageMemoryBarrier(dstImage, (VkAccessFlags)0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
875	};
876
877	for (deUint32 barrierNdx = 0; barrierNdx < DE_LENGTH_OF_ARRAY(layoutBarriers); barrierNdx++)
878	{
879		const VkImageMemoryBarrier* memoryBarrier = &layoutBarriers[barrierNdx];
880		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, (const void * const*)&memoryBarrier);
881	}
882
883	// Add image copy
884	const VkImageCopy				imageCopy			=
885	{
886		{
887			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspect	aspect;
888			0u,								// deUint32			mipLevel;
889			0u,								// deUint32			arrayLayer;
890			1u								// deUint32			arraySize;
891		},											// VkImageSubresourceCopy	srcSubresource;
892		{
893			0,								// int32			x;
894			0,								// int32			y;
895			0								// int32			z;
896		},											// VkOffset3D				srcOffset;
897		{
898			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspect	aspect;
899			0u,								// deUint32			mipLevel;
900			0u,								// deUint32			arrayLayer;
901			1u								// deUint32			arraySize;
902		},											// VkImageSubresourceCopy	destSubResource;
903		{
904			0,								// int32			x;
905			0,								// int32			y;
906			0								// int32			z;
907		},											// VkOffset3D				dstOffset;
908		{
909			width,							// int32			width;
910			height,							// int32			height;
911			1,								// int32			depth
912		}	// VkExtent3D					extent;
913	};
914
915	vk.cmdCopyImage(*cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy);
916
917	// Add destination barrier
918	const VkImageMemoryBarrier		dstBarrier			=
919			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);
920
921	const void* const*				barrier				= (const void* const*)&dstBarrier;
922	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, (const void* const*)&barrier);
923
924	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
925
926	const VkFenceCreateInfo			fenceParams			=
927	{
928		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
929		DE_NULL,								// const void*			pNext;
930		0u										// VkFenceCreateFlags	flags;
931	};
932	const Unique<VkFence>			fence				(createFence(vk, vkDevice, &fenceParams));
933	const VkSubmitInfo				submitInfo			=
934	{
935		VK_STRUCTURE_TYPE_SUBMIT_INFO,
936		DE_NULL,
937		0u,
938		(const VkSemaphore*)DE_NULL,
939		1u,
940		&cmdBuffer.get(),
941		0u,
942		(const VkSemaphore*)DE_NULL,
943	};
944
945
946	// Execute copy
947	VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
948	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
949	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
950}
951
952void ShaderRenderCaseInstance::useSampler2D (deUint32 bindingLocation, deUint32 textureID)
953{
954	DE_ASSERT(textureID < m_textures.size());
955
956	const VkDevice					vkDevice		= m_context.getDevice();
957	const DeviceInterface&			vk				= m_context.getDeviceInterface();
958	const TextureBinding&			textureBinding	= *m_textures[textureID];
959	const tcu::Texture2D&			refTexture		= textureBinding.get2D();
960	const tcu::Sampler&				refSampler		= textureBinding.getSampler();
961	const VkFormat					format			= refTexture.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
962														? VK_FORMAT_R8G8B8A8_UNORM
963														: VK_FORMAT_R8G8B8_UNORM;
964
965	// Create & alloc the image
966	Move<VkImage>					vkTexture;
967	de::MovePtr<Allocation>			allocation;
968
969	if (isSupportedLinearTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
970	{
971		vkTexture = createImage2D(refTexture, format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_LINEAR);
972		allocation = uploadImage2D(refTexture, *vkTexture);
973	}
974	else if (isSupportedOptimalTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
975	{
976		Move<VkImage>				stagingTexture	(createImage2D(refTexture, format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR));
977		de::MovePtr<Allocation>		stagingAlloc	(uploadImage2D(refTexture, *stagingTexture));
978
979		const VkImageUsageFlags		dstUsageFlags	= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
980		vkTexture = createImage2D(refTexture, format, dstUsageFlags, VK_IMAGE_TILING_OPTIMAL);
981		allocation = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
982		VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
983
984		copyTilingImageToOptimal(*stagingTexture, *vkTexture, refTexture.getWidth(), refTexture.getHeight());
985	}
986	else
987	{
988		TCU_THROW(InternalError, "Unable to create 2D image");
989	}
990
991	// Create sampler
992	const bool						compareEnabled	= (refSampler.compare != tcu::Sampler::COMPAREMODE_NONE);
993	const VkSamplerCreateInfo		samplerParams	=
994	{
995		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType	sType;
996		DE_NULL,										// const void*		pNext;
997		(VkSamplerCreateFlags)0,
998		mapFilterMode(refSampler.magFilter),			// VkTexFilter		magFilter;
999		mapFilterMode(refSampler.minFilter),			// VkTexFilter		minFilter;
1000		mapMipmapMode(refSampler.minFilter),			// VkTexMipmapMode	mipMode;
1001		mapWrapMode(refSampler.wrapS),					// VkTexAddressMode	addressModeU;
1002		mapWrapMode(refSampler.wrapT),					// VkTexAddressMode	addressModeV;
1003		mapWrapMode(refSampler.wrapR),					// VkTexAddressMode	addressModeW;
1004		refSampler.lodThreshold,						// float			mipLodBias;
1005		1,												// float			maxAnisotropy;
1006		compareEnabled,									// VkBool32			compareEnable;
1007		mapCompareMode(refSampler.compare),				// VkCompareOp		compareOp;
1008		0.0f,											// float			minLod;
1009		0.0f,											// float			maxLod;
1010		VK_BORDER_COLOR_INT_OPAQUE_WHITE,				// VkBorderColor	boderColor;
1011		VK_FALSE,										// VkBool32			unnormalizerdCoordinates;
1012	};
1013
1014	Move<VkSampler>					sampler			= createSampler(vk, vkDevice, &samplerParams);
1015
1016	const VkImageViewCreateInfo		viewParams		=
1017	{
1018		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1019		NULL,										// const voide*				pNext;
1020		0u,											// VkImageViewCreateFlags	flags;
1021		*vkTexture,									// VkImage					image;
1022		VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
1023		format,										// VkFormat					format;
1024		{
1025			VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
1026			VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
1027			VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
1028			VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
1029		},											// VkChannelMapping			channels;
1030		{
1031			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
1032			0,								// deUint32				baseMipLevel;
1033			1,								// deUint32				mipLevels;
1034			0,								// deUint32				baseArraySlice;
1035			1								// deUint32				arraySize;
1036		},											// VkImageSubresourceRange	subresourceRange;
1037	};
1038
1039	Move<VkImageView>				imageView		= createImageView(vk, vkDevice, &viewParams);
1040
1041	const vk::VkDescriptorImageInfo	descriptor		=
1042	{
1043		sampler.get(),								// VkSampler				sampler;
1044		imageView.get(),							// VkImageView				imageView;
1045		VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			imageLayout;
1046	};
1047
1048	de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
1049	uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1050	uniform->descriptor = descriptor;
1051	uniform->location = bindingLocation;
1052	uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
1053	uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
1054	uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
1055	uniform->alloc = AllocationSp(allocation.release());
1056
1057	m_descriptorSetLayoutBuilder.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_ALL, &uniform->descriptor.sampler);
1058	m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1059
1060	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
1061}
1062
1063void ShaderRenderCaseInstance::setupDefaultInputs (const QuadGrid& quadGrid)
1064{
1065	/* Configuration of the vertex input attributes:
1066		a_position   is at location 0
1067		a_coords     is at location 1
1068		a_unitCoords is at location 2
1069		a_one        is at location 3
1070
1071	  User attributes starts from at the location 4.
1072	*/
1073	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
1074	addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
1075	addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
1076	addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
1077
1078	static const struct
1079	{
1080		BaseAttributeType	type;
1081		int					userNdx;
1082	} userAttributes[] =
1083	{
1084		{ A_IN0, 0 },
1085		{ A_IN1, 1 },
1086		{ A_IN2, 2 },
1087		{ A_IN3, 3 }
1088	};
1089
1090	static const struct
1091	{
1092		BaseAttributeType	matrixType;
1093		int					numCols;
1094		int					numRows;
1095	} matrices[] =
1096	{
1097		{ MAT2,		2, 2 },
1098		{ MAT2x3,	2, 3 },
1099		{ MAT2x4,	2, 4 },
1100		{ MAT3x2,	3, 2 },
1101		{ MAT3,		3, 3 },
1102		{ MAT3x4,	3, 4 },
1103		{ MAT4x2,	4, 2 },
1104		{ MAT4x3,	4, 3 },
1105		{ MAT4,		4, 4 }
1106	};
1107
1108	for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
1109	{
1110		for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
1111		{
1112			if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
1113				continue;
1114
1115			addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
1116		}
1117
1118		for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
1119		{
1120
1121			if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
1122				continue;
1123
1124			const int numCols = matrices[matNdx].numCols;
1125
1126			for (int colNdx = 0; colNdx < numCols; colNdx++)
1127			{
1128				addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(4 * sizeof(float)), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
1129			}
1130		}
1131	}
1132}
1133
1134void ShaderRenderCaseInstance::render (tcu::Surface& result, const QuadGrid& quadGrid)
1135{
1136	const VkDevice										vkDevice					= m_context.getDevice();
1137	const DeviceInterface&								vk							= m_context.getDeviceInterface();
1138	const VkQueue										queue						= m_context.getUniversalQueue();
1139	const deUint32										queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1140
1141	// Create color image
1142	{
1143		const VkImageCreateInfo							colorImageParams			=
1144		{
1145			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType		sType;
1146			DE_NULL,																	// const void*			pNext;
1147			0u,																			// VkImageCreateFlags	flags;
1148			VK_IMAGE_TYPE_2D,															// VkImageType			imageType;
1149			m_colorFormat,																// VkFormat				format;
1150			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D			extent;
1151			1u,																			// deUint32				mipLevels;
1152			1u,																			// deUint32				arraySize;
1153			VK_SAMPLE_COUNT_1_BIT,														// deUint32				samples;
1154			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling		tiling;
1155			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags	usage;
1156			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode;
1157			1u,																			// deUint32				queueFamilyCount;
1158			&queueFamilyIndex,															// const deUint32*		pQueueFamilyIndices;
1159			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout		initialLayout;
1160		};
1161
1162		m_colorImage = createImage(vk, vkDevice, &colorImageParams);
1163
1164		// Allocate and bind color image memory
1165		m_colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1166		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1167	}
1168
1169	// Create color attachment view
1170	{
1171		const VkImageViewCreateInfo						colorImageViewParams		=
1172		{
1173			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1174			DE_NULL,											// const void*				pNext;
1175			0u,													// VkImageViewCreateFlags	flags;
1176			*m_colorImage,										// VkImage					image;
1177			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1178			m_colorFormat,										// VkFormat					format;
1179			{
1180				VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
1181				VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
1182				VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
1183				VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
1184			},													// VkChannelMapping			channels;
1185			{
1186				VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
1187				0,								// deUint32				baseMipLevel;
1188				1,								// deUint32				mipLevels;
1189				0,								// deUint32				baseArraySlice;
1190				1								// deUint32				arraySize;
1191			},													// VkImageSubresourceRange	subresourceRange;
1192		};
1193
1194		m_colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
1195	}
1196
1197	// Create render pass
1198	{
1199		const VkAttachmentDescription					attachmentDescription		=
1200		{
1201			(VkAttachmentDescriptionFlags)0,
1202			m_colorFormat,										// VkFormat						format;
1203			VK_SAMPLE_COUNT_1_BIT,								// deUint32						samples;
1204			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			loadOp;
1205			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp			storeOp;
1206			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp			stencilLoadOp;
1207			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			stencilStoreOp;
1208			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				initialLayout;
1209			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				finalLayout;
1210		};
1211
1212		const VkAttachmentReference						attachmentReference			=
1213		{
1214			0u,													// deUint32			attachment;
1215			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1216		};
1217
1218		const VkSubpassDescription						subpassDescription			=
1219		{
1220			0u,													// VkSubpassDescriptionFlags	flags;
1221			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
1222			0u,													// deUint32						inputCount;
1223			DE_NULL,											// constVkAttachmentReference*	pInputAttachments;
1224			1u,													// deUint32						colorCount;
1225			&attachmentReference,								// constVkAttachmentReference*	pColorAttachments;
1226			DE_NULL,											// constVkAttachmentReference*	pResolveAttachments;
1227			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
1228			0u,													// deUint32						preserveCount;
1229			DE_NULL												// constVkAttachmentReference*	pPreserveAttachments;
1230		};
1231
1232		const VkRenderPassCreateInfo					renderPassParams			=
1233		{
1234			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
1235			DE_NULL,											// const void*						pNext;
1236			(VkRenderPassCreateFlags)0,
1237			1u,													// deUint32							attachmentCount;
1238			&attachmentDescription,								// const VkAttachmentDescription*	pAttachments;
1239			1u,													// deUint32							subpassCount;
1240			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
1241			0u,													// deUint32							dependencyCount;
1242			DE_NULL												// const VkSubpassDependency*		pDependencies;
1243		};
1244
1245		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
1246	}
1247
1248	// Create framebuffer
1249	{
1250		const VkFramebufferCreateInfo					framebufferParams			=
1251		{
1252			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
1253			DE_NULL,											// const void*					pNext;
1254			(VkFramebufferCreateFlags)0,
1255			*m_renderPass,										// VkRenderPass					renderPass;
1256			1u,													// deUint32						attachmentCount;
1257			&*m_colorImageView,									// const VkImageView*			pAttachments;
1258			(deUint32)m_renderSize.x(),							// deUint32						width;
1259			(deUint32)m_renderSize.y(),							// deUint32						height;
1260			1u													// deUint32						layers;
1261		};
1262
1263		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1264	}
1265
1266	// Create descriptors
1267	{
1268		setupUniforms(quadGrid.getConstCoords());
1269
1270		m_descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
1271		m_descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1272
1273		{
1274			const VkDescriptorSetAllocateInfo	allocInfo	=
1275			{
1276				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1277				DE_NULL,
1278				*m_descriptorPool,
1279				1u,
1280				&m_descriptorSetLayout.get(),
1281			};
1282
1283			m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
1284		}
1285
1286		for (deUint32 i = 0; i < m_uniformInfos.size(); i++)
1287		{
1288			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1289			deUint32 location = uniformInfo->location;
1290
1291			if (uniformInfo->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
1292			{
1293				const BufferUniform*	bufferInfo	= dynamic_cast<const BufferUniform*>(uniformInfo);
1294
1295				m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &bufferInfo->descriptor);
1296			}
1297			else if (uniformInfo->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1298			{
1299				const SamplerUniform*	samplerInfo	= dynamic_cast<const SamplerUniform*>(uniformInfo);
1300
1301				m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &samplerInfo->descriptor);
1302			}
1303			else
1304				DE_FATAL("Impossible");
1305		}
1306
1307		m_descriptorSetUpdateBuilder.update(vk, vkDevice);
1308	}
1309
1310	// Create pipeline layout
1311	{
1312		const VkPipelineLayoutCreateInfo				pipelineLayoutParams		=
1313		{
1314			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1315			DE_NULL,											// const void*					pNext;
1316			(VkPipelineLayoutCreateFlags)0,
1317			1u,													// deUint32						descriptorSetCount;
1318			&*m_descriptorSetLayout,							// const VkDescriptorSetLayout*	pSetLayouts;
1319			0u,													// deUint32						pushConstantRangeCount;
1320			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
1321		};
1322
1323		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1324	}
1325
1326	// Create shaders
1327	{
1328		m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
1329		m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
1330	}
1331
1332	// Create pipeline
1333	{
1334		const VkPipelineShaderStageCreateInfo			shaderStageParams[2]		=
1335		{
1336			{
1337				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
1338				DE_NULL,													// const void*					pNext;
1339				(VkPipelineShaderStageCreateFlags)0,
1340				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStage				stage;
1341				*m_vertexShaderModule,										// VkShader						shader;
1342				"main",
1343				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
1344			},
1345			{
1346				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
1347				DE_NULL,													// const void*					pNext;
1348				(VkPipelineShaderStageCreateFlags)0,
1349				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStage				stage;
1350				*m_fragmentShaderModule,									// VkShader						shader;
1351				"main",
1352				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
1353			}
1354		};
1355
1356		// Add test case specific attributes
1357		if (m_attribFunc)
1358			m_attribFunc(*this, quadGrid.getNumVertices());
1359
1360		// Add base attributes
1361		setupDefaultInputs(quadGrid);
1362
1363		const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams		=
1364		{
1365			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1366			DE_NULL,														// const void*								pNext;
1367			(VkPipelineVertexInputStateCreateFlags)0,
1368			(deUint32)m_vertexBindingDescription.size(),					// deUint32									bindingCount;
1369			&m_vertexBindingDescription[0],									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1370			(deUint32)m_vertexattributeDescription.size(),					// deUint32									attributeCount;
1371			&m_vertexattributeDescription[0],								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1372		};
1373
1374		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams	=
1375		{
1376			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType		sType;
1377			DE_NULL,														// const void*			pNext;
1378			(VkPipelineInputAssemblyStateCreateFlags)0,
1379			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology	topology;
1380			false															// VkBool32				primitiveRestartEnable;
1381		};
1382
1383		const VkViewport								viewport					=
1384		{
1385			0.0f,						// float	originX;
1386			0.0f,						// float	originY;
1387			(float)m_renderSize.x(),	// float	width;
1388			(float)m_renderSize.y(),	// float	height;
1389			0.0f,						// float	minDepth;
1390			1.0f						// float	maxDepth;
1391		};
1392
1393		const VkRect2D									scissor						=
1394		{
1395			{
1396				0u,					// deUint32	x;
1397				0u,					// deUint32	y;
1398			},							// VkOffset2D	offset;
1399			{
1400				m_renderSize.x(),	// deUint32	width;
1401				m_renderSize.y(),	// deUint32	height;
1402			},							// VkExtent2D	extent;
1403		};
1404
1405		const VkPipelineViewportStateCreateInfo			viewportStateParams			=
1406		{
1407			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType		sType;
1408			DE_NULL,														// const void*			pNext;
1409			(VkPipelineViewportStateCreateFlags)0,
1410			1u,																// deUint32				viewportCount;
1411			&viewport,														// const VkViewport*	pViewports;
1412			1u,																// deUint32				scissorsCount;
1413			&scissor,														// const VkRect2D*		pScissors;
1414		};
1415
1416		const VkPipelineRasterizationStateCreateInfo	rasterStateParams			=
1417		{
1418			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType	sType;
1419			DE_NULL,														// const void*		pNext;
1420			(VkPipelineRasterizationStateCreateFlags)0,
1421			false,															// VkBool32			depthClipEnable;
1422			false,															// VkBool32			rasterizerDiscardEnable;
1423			VK_POLYGON_MODE_FILL,											// VkFillMode		fillMode;
1424			VK_CULL_MODE_NONE,												// VkCullMode		cullMode;
1425			VK_FRONT_FACE_COUNTER_CLOCKWISE,									// VkFrontFace		frontFace;
1426			false,															// VkBool32			depthBiasEnable;
1427			0.0f,															// float			depthBias;
1428			0.0f,															// float			depthBiasClamp;
1429			0.0f,															// float			slopeScaledDepthBias;
1430			1.0f,															// float			lineWidth;
1431		};
1432
1433		const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState	=
1434		{
1435			false,															// VkBool32			blendEnable;
1436			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendColor;
1437			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendColor;
1438			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpColor;
1439			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendAlpha;
1440			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendAlpha;
1441			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpAlpha;
1442			(VK_COLOR_COMPONENT_R_BIT |
1443			 VK_COLOR_COMPONENT_G_BIT |
1444			 VK_COLOR_COMPONENT_B_BIT |
1445			 VK_COLOR_COMPONENT_A_BIT),										// VkChannelFlags	channelWriteMask;
1446		};
1447
1448		const VkPipelineColorBlendStateCreateInfo		colorBlendStateParams		=
1449		{
1450			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1451			DE_NULL,													// const void*									pNext;
1452			(VkPipelineColorBlendStateCreateFlags)0,
1453			false,														// VkBool32										logicOpEnable;
1454			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1455			1u,															// deUint32										attachmentCount;
1456			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1457			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1458		};
1459
1460		const VkPipelineDynamicStateCreateInfo			dynamicStateInfo			=
1461		{
1462			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,		// VkStructureType				sType;
1463			DE_NULL,													// const void*					pNext;
1464			(VkPipelineDynamicStateCreateFlags)0,
1465			0u,															// deUint32						dynamicStateCount;
1466			DE_NULL														// const VkDynamicState*		pDynamicStates;
1467		};
1468
1469		const VkGraphicsPipelineCreateInfo				graphicsPipelineParams		=
1470		{
1471			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1472			DE_NULL,											// const void*										pNext;
1473			0u,													// VkPipelineCreateFlags							flags;
1474			2u,													// deUint32											stageCount;
1475			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
1476			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1477			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1478			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1479			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1480			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
1481			DE_NULL,											// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1482			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1483			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1484			&dynamicStateInfo,									// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1485			*m_pipelineLayout,									// VkPipelineLayout									layout;
1486			*m_renderPass,										// VkRenderPass										renderPass;
1487			0u,													// deUint32											subpass;
1488			0u,													// VkPipeline										basePipelineHandle;
1489			0u													// deInt32											basePipelineIndex;
1490		};
1491
1492		m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1493	}
1494
1495	// Create vertex indices buffer
1496	{
1497		const VkDeviceSize								indiceBufferSize			= quadGrid.getNumTriangles() * 3 * sizeof(deUint16);
1498		const VkBufferCreateInfo						indiceBufferParams			=
1499		{
1500			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1501			DE_NULL,									// const void*			pNext;
1502			0u,											// VkBufferCreateFlags	flags;
1503			indiceBufferSize,							// VkDeviceSize			size;
1504			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1505			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1506			1u,											// deUint32				queueFamilyCount;
1507			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1508		};
1509
1510		m_indiceBuffer		= createBuffer(vk, vkDevice, &indiceBufferParams);
1511		m_indiceBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indiceBuffer), MemoryRequirement::HostVisible);
1512
1513		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indiceBuffer, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset()));
1514
1515		// Load vertice indices into buffer
1516		deMemcpy(m_indiceBufferAlloc->getHostPtr(), quadGrid.getIndices(), (size_t)indiceBufferSize);
1517		flushMappedMemoryRange(vk, vkDevice, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset(), indiceBufferSize);
1518	}
1519
1520	// Create command pool
1521	{
1522		const VkCommandPoolCreateInfo					cmdPoolParams				=
1523		{
1524			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType		sType;
1525			DE_NULL,										// const void*			pNext;
1526			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCmdPoolCreateFlags	flags;
1527			queueFamilyIndex,								// deUint32				queueFamilyIndex;
1528		};
1529
1530		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1531	}
1532
1533	// Create command buffer
1534	{
1535		const VkCommandBufferAllocateInfo				cmdBufferParams				=
1536		{
1537			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1538			DE_NULL,										// const void*				pNext;
1539			*m_cmdPool,										// VkCmdPool				cmdPool;
1540			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
1541			1u												// deUint32					bufferCount;
1542		};
1543
1544		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
1545		{
1546			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
1547			DE_NULL,										// const void*				pNext;
1548			0u,												// VkCmdBufferOptimizeFlags	flags;
1549			DE_NULL,										// VkRenderPass				renderPass;
1550			0u,												// deUint32					subpass;
1551			DE_NULL,										// VkFramebuffer			framebuffer;
1552			VK_FALSE,
1553			(VkQueryControlFlags)0,
1554			(VkQueryPipelineStatisticFlags)0,
1555		};
1556
1557		const VkClearValue								clearValues					= makeClearValueColorF32(m_clearColor.x(),
1558																											 m_clearColor.y(),
1559																											 m_clearColor.z(),
1560																											 m_clearColor.w());
1561
1562		const VkRenderPassBeginInfo						renderPassBeginInfo			=
1563		{
1564			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
1565			DE_NULL,												// const void*			pNext;
1566			*m_renderPass,											// VkRenderPass			renderPass;
1567			*m_framebuffer,											// VkFramebuffer		framebuffer;
1568			{ { 0, 0 },  {m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
1569			1,														// deUint32				clearValueCount;
1570			&clearValues,											// const VkClearValue*	pClearValues;
1571		};
1572
1573		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1574
1575		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1576
1577		// Add texture barriers
1578		std::vector<VkImageMemoryBarrier> barriers;
1579		std::vector<void*> barrierPtrs;
1580
1581		for(deUint32 i = 0; i < m_uniformInfos.size(); i++)
1582		{
1583			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1584
1585			if (uniformInfo->type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1586			{
1587				continue;
1588			}
1589
1590			const SamplerUniform*		sampler			= static_cast<const SamplerUniform*>(uniformInfo);
1591
1592			const VkAccessFlags			outputMask		= VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
1593			const VkImageMemoryBarrier	textureBarrier	= createImageMemoryBarrier(sampler->image->get(), outputMask, 0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1594
1595			barriers.push_back(textureBarrier);
1596			barrierPtrs.push_back((void*)&barriers.back());
1597		}
1598
1599		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, (deUint32)barrierPtrs.size(), (barrierPtrs.size() ? (const void * const*)&barrierPtrs[0] : DE_NULL));
1600
1601		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1602
1603		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1604		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &*m_descriptorSet, 0u, DE_NULL);
1605		vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indiceBuffer, 0, VK_INDEX_TYPE_UINT16);
1606
1607		const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
1608		const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
1609
1610		std::vector<VkBuffer> buffers(numberOfVertexAttributes);
1611		for (size_t i = 0; i < numberOfVertexAttributes; i++)
1612		{
1613			buffers[i] = m_vertexBuffers[i].get()->get();
1614		}
1615
1616		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
1617		vk.cmdDrawIndexed(*m_cmdBuffer, quadGrid.getNumTriangles() * 3, 1, 0, 0, 0);
1618
1619		vk.cmdEndRenderPass(*m_cmdBuffer);
1620		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1621	}
1622
1623	// Create fence
1624	{
1625		const VkFenceCreateInfo							fenceParams					=
1626		{
1627			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
1628			DE_NULL,								// const void*			pNext;
1629			0u										// VkFenceCreateFlags	flags;
1630		};
1631		m_fence = createFence(vk, vkDevice, &fenceParams);
1632	}
1633
1634	// Execute Draw
1635	{
1636		const VkSubmitInfo	submitInfo	=
1637		{
1638			VK_STRUCTURE_TYPE_SUBMIT_INFO,
1639			DE_NULL,
1640			0u,
1641			(const VkSemaphore*)DE_NULL,
1642			1u,
1643			&m_cmdBuffer.get(),
1644			0u,
1645			(const VkSemaphore*)DE_NULL,
1646		};
1647
1648		VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1649		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1650		VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1651	}
1652
1653	// Read back the result
1654	{
1655		const VkDeviceSize								imageSizeBytes				= (VkDeviceSize)(sizeof(deUint32) * m_renderSize.x() * m_renderSize.y());
1656		const VkBufferCreateInfo						readImageBufferParams		=
1657		{
1658			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//  VkStructureType		sType;
1659			DE_NULL,									//  const void*			pNext;
1660			0u,											//  VkBufferCreateFlags	flags;
1661			imageSizeBytes,								//  VkDeviceSize		size;
1662			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//  VkBufferUsageFlags	usage;
1663			VK_SHARING_MODE_EXCLUSIVE,					//  VkSharingMode		sharingMode;
1664			1u,											//  deUint32			queueFamilyCount;
1665			&queueFamilyIndex,							//  const deUint32*		pQueueFamilyIndices;
1666		};
1667		const Unique<VkBuffer>							readImageBuffer				(createBuffer(vk, vkDevice, &readImageBufferParams));
1668		const de::UniquePtr<Allocation>					readImageBufferMemory		(m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
1669
1670		VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
1671
1672		// Copy image to buffer
1673		const VkCommandBufferAllocateInfo				cmdBufferParams				=
1674		{
1675			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1676			DE_NULL,										// const void*				pNext;
1677			*m_cmdPool,										// VkCmdPool				cmdPool;
1678			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
1679			1u												// deUint32					bufferCount;
1680		};
1681
1682		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
1683		{
1684			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
1685			DE_NULL,										// const void*				pNext;
1686			0u,												// VkCmdBufferOptimizeFlags	flags;
1687			DE_NULL,										// VkRenderPass				renderPass;
1688			0u,												// deUint32					subpass;
1689			DE_NULL,										// VkFramebuffer			framebuffer;
1690			VK_FALSE,
1691			(VkQueryControlFlags)0,
1692			(VkQueryPipelineStatisticFlags)0,
1693		};
1694
1695		const Move<VkCommandBuffer>						cmdBuffer					= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1696
1697		const VkBufferImageCopy							copyParams					=
1698		{
1699			0u,											// VkDeviceSize			bufferOffset;
1700			(deUint32)m_renderSize.x(),					// deUint32				bufferRowLength;
1701			(deUint32)m_renderSize.y(),					// deUint32				bufferImageHeight;
1702			{
1703				VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspect		aspect;
1704				0u,									// deUint32				mipLevel;
1705				0u,									// deUint32				arraySlice;
1706				1u,									// deUint32				arraySize;
1707			},											// VkImageSubresourceCopy	imageSubresource;
1708			{ 0u, 0u, 0u },								// VkOffset3D			imageOffset;
1709			{ m_renderSize.x(), m_renderSize.y(), 1u }	// VkExtent3D			imageExtent;
1710		};
1711		const VkSubmitInfo								submitInfo					=
1712		{
1713			VK_STRUCTURE_TYPE_SUBMIT_INFO,
1714			DE_NULL,
1715			0u,
1716			(const VkSemaphore*)DE_NULL,
1717			1u,
1718			&cmdBuffer.get(),
1719			0u,
1720			(const VkSemaphore*)DE_NULL,
1721		};
1722
1723		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1724		vk.cmdCopyImageToBuffer(*cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
1725		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1726
1727		VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1728		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1729		VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1730
1731		invalidateMappedMemoryRange(vk, vkDevice, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset(), imageSizeBytes);
1732
1733		const tcu::TextureFormat						resultFormat				(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1734		const tcu::ConstPixelBufferAccess				resultAccess				(resultFormat, m_renderSize.x(), m_renderSize.y(), 1, readImageBufferMemory->getHostPtr());
1735
1736		tcu::copy(result.getAccess(), resultAccess);
1737	}
1738}
1739
1740void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
1741{
1742	// Buffer info.
1743	const int				width		= result.getWidth();
1744	const int				height		= result.getHeight();
1745	const int				gridSize	= quadGrid.getGridSize();
1746	const int				stride		= gridSize + 1;
1747	const bool				hasAlpha	= true; // \todo [2015-09-07 elecro] add correct alpha check
1748	ShaderEvalContext		evalCtx		(quadGrid);
1749
1750	// Evaluate color for each vertex.
1751	std::vector<tcu::Vec4>	colors		((gridSize + 1) * (gridSize + 1));
1752	for (int y = 0; y < gridSize+1; y++)
1753	for (int x = 0; x < gridSize+1; x++)
1754	{
1755		const float	sx			= (float)x / (float)gridSize;
1756		const float	sy			= (float)y / (float)gridSize;
1757		const int	vtxNdx		= ((y * (gridSize+1)) + x);
1758
1759		evalCtx.reset(sx, sy);
1760		m_evaluator.evaluate(evalCtx);
1761		DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
1762		tcu::Vec4 color = evalCtx.color;
1763
1764		if (!hasAlpha)
1765			color.w() = 1.0f;
1766
1767		colors[vtxNdx] = color;
1768	}
1769
1770	// Render quads.
1771	for (int y = 0; y < gridSize; y++)
1772	for (int x = 0; x < gridSize; x++)
1773	{
1774		const float		x0		= (float)x       / (float)gridSize;
1775		const float		x1		= (float)(x + 1) / (float)gridSize;
1776		const float		y0		= (float)y       / (float)gridSize;
1777		const float		y1		= (float)(y + 1) / (float)gridSize;
1778
1779		const float		sx0		= x0 * (float)width;
1780		const float		sx1		= x1 * (float)width;
1781		const float		sy0		= y0 * (float)height;
1782		const float		sy1		= y1 * (float)height;
1783		const float		oosx	= 1.0f / (sx1 - sx0);
1784		const float		oosy	= 1.0f / (sy1 - sy0);
1785
1786		const int		ix0		= deCeilFloatToInt32(sx0 - 0.5f);
1787		const int		ix1		= deCeilFloatToInt32(sx1 - 0.5f);
1788		const int		iy0		= deCeilFloatToInt32(sy0 - 0.5f);
1789		const int		iy1		= deCeilFloatToInt32(sy1 - 0.5f);
1790
1791		const int		v00		= (y * stride) + x;
1792		const int		v01		= (y * stride) + x + 1;
1793		const int		v10		= ((y + 1) * stride) + x;
1794		const int		v11		= ((y + 1) * stride) + x + 1;
1795		const tcu::Vec4	c00		= colors[v00];
1796		const tcu::Vec4	c01		= colors[v01];
1797		const tcu::Vec4	c10		= colors[v10];
1798		const tcu::Vec4	c11		= colors[v11];
1799
1800		//printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
1801
1802		for (int iy = iy0; iy < iy1; iy++)
1803		for (int ix = ix0; ix < ix1; ix++)
1804		{
1805			DE_ASSERT(deInBounds32(ix, 0, width));
1806			DE_ASSERT(deInBounds32(iy, 0, height));
1807
1808			const float			sfx		= (float)ix + 0.5f;
1809			const float			sfy		= (float)iy + 0.5f;
1810			const float			fx1		= deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
1811			const float			fy1		= deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
1812
1813			// Triangle quad interpolation.
1814			const bool			tri		= fx1 + fy1 <= 1.0f;
1815			const float			tx		= tri ? fx1 : (1.0f-fx1);
1816			const float			ty		= tri ? fy1 : (1.0f-fy1);
1817			const tcu::Vec4&	t0		= tri ? c00 : c11;
1818			const tcu::Vec4&	t1		= tri ? c01 : c10;
1819			const tcu::Vec4&	t2		= tri ? c10 : c01;
1820			const tcu::Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
1821
1822			result.setPixel(ix, iy, tcu::RGBA(color));
1823		}
1824	}
1825}
1826
1827void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
1828{
1829	// Buffer info.
1830	const int			width		= result.getWidth();
1831	const int			height		= result.getHeight();
1832	const bool			hasAlpha	= true;  // \todo [2015-09-07 elecro] add correct alpha check
1833	ShaderEvalContext	evalCtx		(quadGrid);
1834
1835	// Render.
1836	for (int y = 0; y < height; y++)
1837	for (int x = 0; x < width; x++)
1838	{
1839		const float sx = ((float)x + 0.5f) / (float)width;
1840		const float sy = ((float)y + 0.5f) / (float)height;
1841
1842		evalCtx.reset(sx, sy);
1843		m_evaluator.evaluate(evalCtx);
1844		// Select either clear color or computed color based on discarded bit.
1845		tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
1846
1847		if (!hasAlpha)
1848			color.w() = 1.0f;
1849
1850		result.setPixel(x, y, tcu::RGBA(color));
1851	}
1852}
1853
1854bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
1855{
1856	return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_RESULT);
1857}
1858
1859} // sr
1860} // vkt
1861