vktShaderRender.cpp revision e148980e7f95d8a113a7dc84b13ca9906f33869f
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, 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::IVec2 ShaderRenderCaseInstance::getViewportSize (void) const
751{
752	return tcu::IVec2(de::min(m_renderSize.x(), s_maxRenderWidth),
753					  de::min(m_renderSize.y(), s_maxRenderHeight));
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		{ texture.getWidth(), texture.getHeight(), 1 },				// VkExtend3D				extent;
773		1u,															// deUint32					mipLevels;
774		1u,															// deUint32					arraySize;
775		VK_SAMPLE_COUNT_1_BIT,										// deUint32					samples;
776		tiling,														// VkImageTiling			tiling;
777		usage,														// VkImageUsageFlags		usage;
778		VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode			sharingMode;
779		1,															// deuint32					queueFamilyCount;
780		&queueFamilyIndex,											// const deUint32*			pQueueFamilyIndices;
781		VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			initialLayout;
782	};
783
784	Move<VkImage>			vkTexture			= createImage(vk, vkDevice, &imageCreateInfo);
785	return vkTexture;
786}
787
788de::MovePtr<Allocation> ShaderRenderCaseInstance::uploadImage2D (const tcu::Texture2D&	refTexture,
789																 const VkImage&			vkTexture)
790{
791	const VkDevice				vkDevice	= m_context.getDevice();
792	const DeviceInterface&		vk			= m_context.getDeviceInterface();
793
794	de::MovePtr<Allocation>		allocation	= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, vkTexture), MemoryRequirement::HostVisible);
795	VK_CHECK(vk.bindImageMemory(vkDevice, vkTexture, allocation->getMemory(), allocation->getOffset()));
796
797	const VkImageSubresource	subres				=
798	{
799		VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
800		0u,							// deUint32				mipLevel;
801		0u							// deUint32				arraySlice
802	};
803
804	VkSubresourceLayout layout;
805	vk.getImageSubresourceLayout(vkDevice, vkTexture, &subres, &layout);
806
807	tcu::ConstPixelBufferAccess	access		= refTexture.getLevel(0);
808	tcu::PixelBufferAccess		destAccess	(refTexture.getFormat(), refTexture.getWidth(), refTexture.getHeight(), 1, allocation->getHostPtr());
809
810	tcu::copy(destAccess, access);
811
812	flushMappedMemoryRange(vk, vkDevice, allocation->getMemory(), allocation, layout.size);
813
814	return allocation;
815}
816
817void ShaderRenderCaseInstance::copyTilingImageToOptimal	(const vk::VkImage&	srcImage,
818														 const vk::VkImage&	dstImage,
819														 deInt32 width,
820														 deInt32 height)
821{
822	const VkDevice						vkDevice			= m_context.getDevice();
823	const DeviceInterface&				vk					= m_context.getDeviceInterface();
824	const VkQueue						queue				= m_context.getUniversalQueue();
825	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
826
827	// Create command pool
828	const VkCommandPoolCreateInfo		cmdPoolParams		=
829	{
830		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,	// VkStructureType		sType;
831		DE_NULL,									// const void*			pNext;
832		VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,		// VkCmdPoolCreateFlags	flags;
833		queueFamilyIndex,							// deUint32				queueFamilyIndex;
834	};
835
836	Move<VkCommandPool>					cmdPool				= createCommandPool(vk, vkDevice, &cmdPoolParams);
837
838	// Create command buffer
839	const VkCommandBufferAllocateInfo	cmdBufferParams		=
840	{
841		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
842		DE_NULL,										// const void*				pNext;
843		*cmdPool,										// VkCommandPool			commandPool;
844		VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
845		1u												// deUint32					bufferCount;
846	};
847
848	const VkCommandBufferUsageFlags		usageFlags			= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
849	const VkCommandBufferBeginInfo		cmdBufferBeginInfo	=
850	{
851		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType				sType;
852		DE_NULL,										// const void*					pNext;
853		usageFlags,										// VkCommandBufferUsageFlags	flags;
854		DE_NULL,										// VkRenderPass					renderPass;
855		0u,												// deUint32						subpass;
856		DE_NULL,										// VkFramebuffer				framebuffer;
857		VK_FALSE,										// VkBool32						occlusionQueryEnable;
858		(VkQueryControlFlags)0,
859		(VkQueryPipelineStatisticFlags)0,
860	};
861
862	Move<VkCommandBuffer>				cmdBuffer			= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
863
864	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
865
866	// Add image barriers
867	const VkImageMemoryBarrier			layoutBarriers[2]	=
868	{
869		createImageMemoryBarrier(srcImage, (VkAccessFlags)0u, (VkAccessFlags)0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
870		createImageMemoryBarrier(dstImage, (VkAccessFlags)0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
871	};
872
873	for (deUint32 barrierNdx = 0; barrierNdx < DE_LENGTH_OF_ARRAY(layoutBarriers); barrierNdx++)
874	{
875		const VkImageMemoryBarrier* memoryBarrier = &layoutBarriers[barrierNdx];
876		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, (const void * const*)&memoryBarrier);
877	}
878
879	// Add image copy
880	const VkImageCopy				imageCopy			=
881	{
882		{
883			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspect	aspect;
884			0u,								// deUint32			mipLevel;
885			0u,								// deUint32			arrayLayer;
886			1u								// deUint32			arraySize;
887		},											// VkImageSubresourceCopy	srcSubresource;
888		{
889			0,								// int32			x;
890			0,								// int32			y;
891			0								// int32			z;
892		},											// VkOffset3D				srcOffset;
893		{
894			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspect	aspect;
895			0u,								// deUint32			mipLevel;
896			0u,								// deUint32			arrayLayer;
897			1u								// deUint32			arraySize;
898		},											// VkImageSubresourceCopy	destSubResource;
899		{
900			0,								// int32			x;
901			0,								// int32			y;
902			0								// int32			z;
903		},											// VkOffset3D				dstOffset;
904		{
905			width,							// int32			width;
906			height,							// int32			height;
907			1,								// int32			depth
908		}	// VkExtent3D					extent;
909	};
910
911	vk.cmdCopyImage(*cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy);
912
913	// Add destination barrier
914	const VkImageMemoryBarrier		dstBarrier			=
915			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);
916
917	const void* const*				barrier				= (const void* const*)&dstBarrier;
918	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, (const void* const*)&barrier);
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		1u,
936		&cmdBuffer.get(),
937		0u,
938		(const VkSemaphore*)DE_NULL,
939	};
940
941
942	// Execute copy
943	VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
944	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
945	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
946}
947
948void ShaderRenderCaseInstance::useSampler2D (deUint32 bindingLocation, deUint32 textureID)
949{
950	DE_ASSERT(textureID < m_textures.size());
951
952	const VkDevice					vkDevice		= m_context.getDevice();
953	const DeviceInterface&			vk				= m_context.getDeviceInterface();
954	const TextureBinding&			textureBinding	= *m_textures[textureID];
955	const tcu::Texture2D&			refTexture		= textureBinding.get2D();
956	const tcu::Sampler&				refSampler		= textureBinding.getSampler();
957	const VkFormat					format			= refTexture.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
958														? VK_FORMAT_R8G8B8A8_UNORM
959														: VK_FORMAT_R8G8B8_UNORM;
960
961	// Create & alloc the image
962	Move<VkImage>					vkTexture;
963	de::MovePtr<Allocation>			allocation;
964
965	if (isSupportedLinearTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
966	{
967		vkTexture = createImage2D(refTexture, format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_LINEAR);
968		allocation = uploadImage2D(refTexture, *vkTexture);
969	}
970	else if (isSupportedOptimalTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
971	{
972		Move<VkImage>				stagingTexture	(createImage2D(refTexture, format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR));
973		de::MovePtr<Allocation>		stagingAlloc	(uploadImage2D(refTexture, *stagingTexture));
974
975		const VkImageUsageFlags		dstUsageFlags	= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
976		vkTexture = createImage2D(refTexture, format, dstUsageFlags, VK_IMAGE_TILING_OPTIMAL);
977		allocation = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
978		VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
979
980		copyTilingImageToOptimal(*stagingTexture, *vkTexture, refTexture.getWidth(), refTexture.getHeight());
981	}
982	else
983	{
984		TCU_THROW(InternalError, "Unable to create 2D image");
985	}
986
987	// Create sampler
988	const bool						compareEnabled	= (refSampler.compare != tcu::Sampler::COMPAREMODE_NONE);
989	const VkSamplerCreateInfo		samplerParams	=
990	{
991		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType	sType;
992		DE_NULL,										// const void*		pNext;
993		(VkSamplerCreateFlags)0,
994		mapFilterMode(refSampler.magFilter),			// VkTexFilter		magFilter;
995		mapFilterMode(refSampler.minFilter),			// VkTexFilter		minFilter;
996		mapMipmapMode(refSampler.minFilter),			// VkTexMipmapMode	mipMode;
997		mapWrapMode(refSampler.wrapS),					// VkTexAddressMode	addressModeU;
998		mapWrapMode(refSampler.wrapT),					// VkTexAddressMode	addressModeV;
999		mapWrapMode(refSampler.wrapR),					// VkTexAddressMode	addressModeW;
1000		refSampler.lodThreshold,						// float			mipLodBias;
1001		1,												// float			maxAnisotropy;
1002		compareEnabled,									// VkBool32			compareEnable;
1003		mapCompareMode(refSampler.compare),				// VkCompareOp		compareOp;
1004		0.0f,											// float			minLod;
1005		0.0f,											// float			maxLod;
1006		VK_BORDER_COLOR_INT_OPAQUE_WHITE,				// VkBorderColor	boderColor;
1007		VK_FALSE,										// VkBool32			unnormalizerdCoordinates;
1008	};
1009
1010	Move<VkSampler>					sampler			= createSampler(vk, vkDevice, &samplerParams);
1011
1012	const VkImageViewCreateInfo		viewParams		=
1013	{
1014		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1015		NULL,										// const voide*				pNext;
1016		0u,											// VkImageViewCreateFlags	flags;
1017		*vkTexture,									// VkImage					image;
1018		VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
1019		format,										// VkFormat					format;
1020		{
1021			VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
1022			VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
1023			VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
1024			VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
1025		},											// VkChannelMapping			channels;
1026		{
1027			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
1028			0,								// deUint32				baseMipLevel;
1029			1,								// deUint32				mipLevels;
1030			0,								// deUint32				baseArraySlice;
1031			1								// deUint32				arraySize;
1032		},											// VkImageSubresourceRange	subresourceRange;
1033	};
1034
1035	Move<VkImageView>				imageView		= createImageView(vk, vkDevice, &viewParams);
1036
1037	const vk::VkDescriptorImageInfo	descriptor		=
1038	{
1039		sampler.get(),								// VkSampler				sampler;
1040		imageView.get(),							// VkImageView				imageView;
1041		VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			imageLayout;
1042	};
1043
1044	de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
1045	uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1046	uniform->descriptor = descriptor;
1047	uniform->location = bindingLocation;
1048	uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
1049	uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
1050	uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
1051	uniform->alloc = AllocationSp(allocation.release());
1052
1053	m_descriptorSetLayoutBuilder.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_ALL, &uniform->descriptor.sampler);
1054	m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1055
1056	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
1057}
1058
1059void ShaderRenderCaseInstance::setupDefaultInputs (const QuadGrid& quadGrid)
1060{
1061	/* Configuration of the vertex input attributes:
1062		a_position   is at location 0
1063		a_coords     is at location 1
1064		a_unitCoords is at location 2
1065		a_one        is at location 3
1066
1067	  User attributes starts from at the location 4.
1068	*/
1069	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
1070	addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
1071	addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
1072	addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
1073
1074	static const struct
1075	{
1076		BaseAttributeType	type;
1077		int					userNdx;
1078	} userAttributes[] =
1079	{
1080		{ A_IN0, 0 },
1081		{ A_IN1, 1 },
1082		{ A_IN2, 2 },
1083		{ A_IN3, 3 }
1084	};
1085
1086	static const struct
1087	{
1088		BaseAttributeType	matrixType;
1089		int					numCols;
1090		int					numRows;
1091	} matrices[] =
1092	{
1093		{ MAT2,		2, 2 },
1094		{ MAT2x3,	2, 3 },
1095		{ MAT2x4,	2, 4 },
1096		{ MAT3x2,	3, 2 },
1097		{ MAT3,		3, 3 },
1098		{ MAT3x4,	3, 4 },
1099		{ MAT4x2,	4, 2 },
1100		{ MAT4x3,	4, 3 },
1101		{ MAT4,		4, 4 }
1102	};
1103
1104	for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
1105	{
1106		for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
1107		{
1108			if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
1109				continue;
1110
1111			addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
1112		}
1113
1114		for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
1115		{
1116
1117			if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
1118				continue;
1119
1120			const int numCols = matrices[matNdx].numCols;
1121
1122			for (int colNdx = 0; colNdx < numCols; colNdx++)
1123			{
1124				addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(4 * sizeof(float)), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
1125			}
1126		}
1127	}
1128}
1129
1130void ShaderRenderCaseInstance::render (tcu::Surface& result, const QuadGrid& quadGrid)
1131{
1132	const VkDevice										vkDevice					= m_context.getDevice();
1133	const DeviceInterface&								vk							= m_context.getDeviceInterface();
1134	const VkQueue										queue						= m_context.getUniversalQueue();
1135	const deUint32										queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1136
1137	// Create color image
1138	{
1139		const VkImageCreateInfo							colorImageParams			=
1140		{
1141			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType		sType;
1142			DE_NULL,																	// const void*			pNext;
1143			0u,																			// VkImageCreateFlags	flags;
1144			VK_IMAGE_TYPE_2D,															// VkImageType			imageType;
1145			m_colorFormat,																// VkFormat				format;
1146			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D			extent;
1147			1u,																			// deUint32				mipLevels;
1148			1u,																			// deUint32				arraySize;
1149			VK_SAMPLE_COUNT_1_BIT,														// deUint32				samples;
1150			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling		tiling;
1151			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags	usage;
1152			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode;
1153			1u,																			// deUint32				queueFamilyCount;
1154			&queueFamilyIndex,															// const deUint32*		pQueueFamilyIndices;
1155			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout		initialLayout;
1156		};
1157
1158		m_colorImage = createImage(vk, vkDevice, &colorImageParams);
1159
1160		// Allocate and bind color image memory
1161		m_colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1162		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1163	}
1164
1165	// Create color attachment view
1166	{
1167		const VkImageViewCreateInfo						colorImageViewParams		=
1168		{
1169			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1170			DE_NULL,											// const void*				pNext;
1171			0u,													// VkImageViewCreateFlags	flags;
1172			*m_colorImage,										// VkImage					image;
1173			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1174			m_colorFormat,										// VkFormat					format;
1175			{
1176				VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
1177				VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
1178				VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
1179				VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
1180			},													// VkChannelMapping			channels;
1181			{
1182				VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
1183				0,								// deUint32				baseMipLevel;
1184				1,								// deUint32				mipLevels;
1185				0,								// deUint32				baseArraySlice;
1186				1								// deUint32				arraySize;
1187			},													// VkImageSubresourceRange	subresourceRange;
1188		};
1189
1190		m_colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
1191	}
1192
1193	// Create render pass
1194	{
1195		const VkAttachmentDescription					attachmentDescription		=
1196		{
1197			(VkAttachmentDescriptionFlags)0,
1198			m_colorFormat,										// VkFormat						format;
1199			VK_SAMPLE_COUNT_1_BIT,								// deUint32						samples;
1200			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			loadOp;
1201			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp			storeOp;
1202			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp			stencilLoadOp;
1203			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			stencilStoreOp;
1204			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				initialLayout;
1205			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				finalLayout;
1206		};
1207
1208		const VkAttachmentReference						attachmentReference			=
1209		{
1210			0u,													// deUint32			attachment;
1211			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1212		};
1213
1214		const VkSubpassDescription						subpassDescription			=
1215		{
1216			0u,													// VkSubpassDescriptionFlags	flags;
1217			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
1218			0u,													// deUint32						inputCount;
1219			DE_NULL,											// constVkAttachmentReference*	pInputAttachments;
1220			1u,													// deUint32						colorCount;
1221			&attachmentReference,								// constVkAttachmentReference*	pColorAttachments;
1222			DE_NULL,											// constVkAttachmentReference*	pResolveAttachments;
1223			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
1224			0u,													// deUint32						preserveCount;
1225			DE_NULL												// constVkAttachmentReference*	pPreserveAttachments;
1226		};
1227
1228		const VkRenderPassCreateInfo					renderPassParams			=
1229		{
1230			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
1231			DE_NULL,											// const void*						pNext;
1232			(VkRenderPassCreateFlags)0,
1233			1u,													// deUint32							attachmentCount;
1234			&attachmentDescription,								// const VkAttachmentDescription*	pAttachments;
1235			1u,													// deUint32							subpassCount;
1236			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
1237			0u,													// deUint32							dependencyCount;
1238			DE_NULL												// const VkSubpassDependency*		pDependencies;
1239		};
1240
1241		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
1242	}
1243
1244	// Create framebuffer
1245	{
1246		const VkFramebufferCreateInfo					framebufferParams			=
1247		{
1248			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
1249			DE_NULL,											// const void*					pNext;
1250			(VkFramebufferCreateFlags)0,
1251			*m_renderPass,										// VkRenderPass					renderPass;
1252			1u,													// deUint32						attachmentCount;
1253			&*m_colorImageView,									// const VkImageView*			pAttachments;
1254			(deUint32)m_renderSize.x(),							// deUint32						width;
1255			(deUint32)m_renderSize.y(),							// deUint32						height;
1256			1u													// deUint32						layers;
1257		};
1258
1259		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1260	}
1261
1262	// Create descriptors
1263	{
1264		setupUniforms(quadGrid.getConstCoords());
1265
1266		m_descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
1267		m_descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1268
1269		{
1270			const VkDescriptorSetAllocateInfo	allocInfo	=
1271			{
1272				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1273				DE_NULL,
1274				*m_descriptorPool,
1275				1u,
1276				&m_descriptorSetLayout.get(),
1277			};
1278
1279			m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
1280		}
1281
1282		for (deUint32 i = 0; i < m_uniformInfos.size(); i++)
1283		{
1284			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1285			deUint32 location = uniformInfo->location;
1286
1287			if (uniformInfo->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
1288			{
1289				const BufferUniform*	bufferInfo	= dynamic_cast<const BufferUniform*>(uniformInfo);
1290
1291				m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &bufferInfo->descriptor);
1292			}
1293			else if (uniformInfo->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1294			{
1295				const SamplerUniform*	samplerInfo	= dynamic_cast<const SamplerUniform*>(uniformInfo);
1296
1297				m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &samplerInfo->descriptor);
1298			}
1299			else
1300				DE_FATAL("Impossible");
1301		}
1302
1303		m_descriptorSetUpdateBuilder.update(vk, vkDevice);
1304	}
1305
1306	// Create pipeline layout
1307	{
1308		const VkPipelineLayoutCreateInfo				pipelineLayoutParams		=
1309		{
1310			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1311			DE_NULL,											// const void*					pNext;
1312			(VkPipelineLayoutCreateFlags)0,
1313			1u,													// deUint32						descriptorSetCount;
1314			&*m_descriptorSetLayout,							// const VkDescriptorSetLayout*	pSetLayouts;
1315			0u,													// deUint32						pushConstantRangeCount;
1316			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
1317		};
1318
1319		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1320	}
1321
1322	// Create shaders
1323	{
1324		m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
1325		m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
1326	}
1327
1328	// Create pipeline
1329	{
1330		const VkPipelineShaderStageCreateInfo			shaderStageParams[2]		=
1331		{
1332			{
1333				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
1334				DE_NULL,													// const void*					pNext;
1335				(VkPipelineShaderStageCreateFlags)0,
1336				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStage				stage;
1337				*m_vertexShaderModule,										// VkShader						shader;
1338				"main",
1339				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
1340			},
1341			{
1342				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
1343				DE_NULL,													// const void*					pNext;
1344				(VkPipelineShaderStageCreateFlags)0,
1345				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStage				stage;
1346				*m_fragmentShaderModule,									// VkShader						shader;
1347				"main",
1348				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
1349			}
1350		};
1351
1352		// Add test case specific attributes
1353		if (m_attribFunc)
1354			m_attribFunc(*this, quadGrid.getNumVertices());
1355
1356		// Add base attributes
1357		setupDefaultInputs(quadGrid);
1358
1359		const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams		=
1360		{
1361			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1362			DE_NULL,														// const void*								pNext;
1363			(VkPipelineVertexInputStateCreateFlags)0,
1364			(deUint32)m_vertexBindingDescription.size(),					// deUint32									bindingCount;
1365			&m_vertexBindingDescription[0],									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1366			(deUint32)m_vertexattributeDescription.size(),					// deUint32									attributeCount;
1367			&m_vertexattributeDescription[0],								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1368		};
1369
1370		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams	=
1371		{
1372			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType		sType;
1373			DE_NULL,														// const void*			pNext;
1374			(VkPipelineInputAssemblyStateCreateFlags)0,
1375			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology	topology;
1376			false															// VkBool32				primitiveRestartEnable;
1377		};
1378
1379		const VkViewport								viewport					=
1380		{
1381			0.0f,						// float	originX;
1382			0.0f,						// float	originY;
1383			(float)m_renderSize.x(),	// float	width;
1384			(float)m_renderSize.y(),	// float	height;
1385			0.0f,						// float	minDepth;
1386			1.0f						// float	maxDepth;
1387		};
1388
1389		const VkRect2D									scissor						=
1390		{
1391			{
1392				0u,					// deUint32	x;
1393				0u,					// deUint32	y;
1394			},							// VkOffset2D	offset;
1395			{
1396				m_renderSize.x(),	// deUint32	width;
1397				m_renderSize.y(),	// deUint32	height;
1398			},							// VkExtent2D	extent;
1399		};
1400
1401		const VkPipelineViewportStateCreateInfo			viewportStateParams			=
1402		{
1403			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType		sType;
1404			DE_NULL,														// const void*			pNext;
1405			(VkPipelineViewportStateCreateFlags)0,
1406			1u,																// deUint32				viewportCount;
1407			&viewport,														// const VkViewport*	pViewports;
1408			1u,																// deUint32				scissorsCount;
1409			&scissor,														// const VkRect2D*		pScissors;
1410		};
1411
1412		const VkPipelineRasterizationStateCreateInfo	rasterStateParams			=
1413		{
1414			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType	sType;
1415			DE_NULL,														// const void*		pNext;
1416			(VkPipelineRasterizationStateCreateFlags)0,
1417			false,															// VkBool32			depthClipEnable;
1418			false,															// VkBool32			rasterizerDiscardEnable;
1419			VK_POLYGON_MODE_FILL,											// VkFillMode		fillMode;
1420			VK_CULL_MODE_NONE,												// VkCullMode		cullMode;
1421			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace		frontFace;
1422			false,															// VkBool32			depthBiasEnable;
1423			0.0f,															// float			depthBias;
1424			0.0f,															// float			depthBiasClamp;
1425			0.0f,															// float			slopeScaledDepthBias;
1426			1.0f,															// float			lineWidth;
1427		};
1428
1429		const VkPipelineMultisampleStateCreateInfo		multisampleStateParams =
1430		{
1431			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
1432			DE_NULL,														// const void*								pNext;
1433			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
1434			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
1435			VK_FALSE,														// VkBool32									sampleShadingEnable;
1436			0.0f,															// float									minSampleShading;
1437			DE_NULL,														// const VkSampleMask*						pSampleMask;
1438			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
1439			VK_FALSE														// VkBool32									alphaToOneEnable;
1440		};
1441
1442		const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState	=
1443		{
1444			false,															// VkBool32			blendEnable;
1445			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendColor;
1446			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendColor;
1447			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpColor;
1448			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendAlpha;
1449			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendAlpha;
1450			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpAlpha;
1451			(VK_COLOR_COMPONENT_R_BIT |
1452			 VK_COLOR_COMPONENT_G_BIT |
1453			 VK_COLOR_COMPONENT_B_BIT |
1454			 VK_COLOR_COMPONENT_A_BIT),										// VkChannelFlags	channelWriteMask;
1455		};
1456
1457		const VkPipelineColorBlendStateCreateInfo		colorBlendStateParams		=
1458		{
1459			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1460			DE_NULL,													// const void*									pNext;
1461			(VkPipelineColorBlendStateCreateFlags)0,
1462			false,														// VkBool32										logicOpEnable;
1463			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1464			1u,															// deUint32										attachmentCount;
1465			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1466			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1467		};
1468
1469		const VkPipelineDynamicStateCreateInfo			dynamicStateInfo			=
1470		{
1471			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,		// VkStructureType				sType;
1472			DE_NULL,													// const void*					pNext;
1473			(VkPipelineDynamicStateCreateFlags)0,
1474			0u,															// deUint32						dynamicStateCount;
1475			DE_NULL														// const VkDynamicState*		pDynamicStates;
1476		};
1477
1478		const VkGraphicsPipelineCreateInfo				graphicsPipelineParams		=
1479		{
1480			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1481			DE_NULL,											// const void*										pNext;
1482			0u,													// VkPipelineCreateFlags							flags;
1483			2u,													// deUint32											stageCount;
1484			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
1485			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1486			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1487			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1488			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1489			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
1490			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1491			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1492			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1493			&dynamicStateInfo,									// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1494			*m_pipelineLayout,									// VkPipelineLayout									layout;
1495			*m_renderPass,										// VkRenderPass										renderPass;
1496			0u,													// deUint32											subpass;
1497			0u,													// VkPipeline										basePipelineHandle;
1498			0u													// deInt32											basePipelineIndex;
1499		};
1500
1501		m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1502	}
1503
1504	// Create vertex indices buffer
1505	{
1506		const VkDeviceSize								indiceBufferSize			= quadGrid.getNumTriangles() * 3 * sizeof(deUint16);
1507		const VkBufferCreateInfo						indiceBufferParams			=
1508		{
1509			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1510			DE_NULL,									// const void*			pNext;
1511			0u,											// VkBufferCreateFlags	flags;
1512			indiceBufferSize,							// VkDeviceSize			size;
1513			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1514			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1515			1u,											// deUint32				queueFamilyCount;
1516			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1517		};
1518
1519		m_indiceBuffer		= createBuffer(vk, vkDevice, &indiceBufferParams);
1520		m_indiceBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indiceBuffer), MemoryRequirement::HostVisible);
1521
1522		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indiceBuffer, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset()));
1523
1524		// Load vertice indices into buffer
1525		deMemcpy(m_indiceBufferAlloc->getHostPtr(), quadGrid.getIndices(), (size_t)indiceBufferSize);
1526		flushMappedMemoryRange(vk, vkDevice, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset(), indiceBufferSize);
1527	}
1528
1529	// Create command pool
1530	{
1531		const VkCommandPoolCreateInfo					cmdPoolParams				=
1532		{
1533			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType		sType;
1534			DE_NULL,										// const void*			pNext;
1535			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCmdPoolCreateFlags	flags;
1536			queueFamilyIndex,								// deUint32				queueFamilyIndex;
1537		};
1538
1539		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1540	}
1541
1542	// Create command buffer
1543	{
1544		const VkCommandBufferAllocateInfo				cmdBufferParams				=
1545		{
1546			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1547			DE_NULL,										// const void*				pNext;
1548			*m_cmdPool,										// VkCmdPool				cmdPool;
1549			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
1550			1u												// deUint32					bufferCount;
1551		};
1552
1553		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
1554		{
1555			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
1556			DE_NULL,										// const void*				pNext;
1557			0u,												// VkCmdBufferOptimizeFlags	flags;
1558			DE_NULL,										// VkRenderPass				renderPass;
1559			0u,												// deUint32					subpass;
1560			DE_NULL,										// VkFramebuffer			framebuffer;
1561			VK_FALSE,
1562			(VkQueryControlFlags)0,
1563			(VkQueryPipelineStatisticFlags)0,
1564		};
1565
1566		const VkClearValue								clearValues					= makeClearValueColorF32(m_clearColor.x(),
1567																											 m_clearColor.y(),
1568																											 m_clearColor.z(),
1569																											 m_clearColor.w());
1570
1571		const VkRenderPassBeginInfo						renderPassBeginInfo			=
1572		{
1573			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
1574			DE_NULL,												// const void*			pNext;
1575			*m_renderPass,											// VkRenderPass			renderPass;
1576			*m_framebuffer,											// VkFramebuffer		framebuffer;
1577			{ { 0, 0 },  {m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
1578			1,														// deUint32				clearValueCount;
1579			&clearValues,											// const VkClearValue*	pClearValues;
1580		};
1581
1582		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1583
1584		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1585
1586		// Add texture barriers
1587		std::vector<VkImageMemoryBarrier> barriers;
1588		std::vector<void*> barrierPtrs;
1589
1590		for(deUint32 i = 0; i < m_uniformInfos.size(); i++)
1591		{
1592			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1593
1594			if (uniformInfo->type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1595			{
1596				continue;
1597			}
1598
1599			const SamplerUniform*		sampler			= static_cast<const SamplerUniform*>(uniformInfo);
1600
1601			const VkAccessFlags			outputMask		= VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
1602			const VkImageMemoryBarrier	textureBarrier	= createImageMemoryBarrier(sampler->image->get(), outputMask, 0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1603
1604			barriers.push_back(textureBarrier);
1605			barrierPtrs.push_back((void*)&barriers.back());
1606		}
1607
1608		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));
1609
1610		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1611
1612		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1613		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &*m_descriptorSet, 0u, DE_NULL);
1614		vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indiceBuffer, 0, VK_INDEX_TYPE_UINT16);
1615
1616		const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
1617		const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
1618
1619		std::vector<VkBuffer> buffers(numberOfVertexAttributes);
1620		for (size_t i = 0; i < numberOfVertexAttributes; i++)
1621		{
1622			buffers[i] = m_vertexBuffers[i].get()->get();
1623		}
1624
1625		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
1626		vk.cmdDrawIndexed(*m_cmdBuffer, quadGrid.getNumTriangles() * 3, 1, 0, 0, 0);
1627
1628		vk.cmdEndRenderPass(*m_cmdBuffer);
1629		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1630	}
1631
1632	// Create fence
1633	{
1634		const VkFenceCreateInfo							fenceParams					=
1635		{
1636			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
1637			DE_NULL,								// const void*			pNext;
1638			0u										// VkFenceCreateFlags	flags;
1639		};
1640		m_fence = createFence(vk, vkDevice, &fenceParams);
1641	}
1642
1643	// Execute Draw
1644	{
1645		const VkSubmitInfo	submitInfo	=
1646		{
1647			VK_STRUCTURE_TYPE_SUBMIT_INFO,
1648			DE_NULL,
1649			0u,
1650			(const VkSemaphore*)DE_NULL,
1651			1u,
1652			&m_cmdBuffer.get(),
1653			0u,
1654			(const VkSemaphore*)DE_NULL,
1655		};
1656
1657		VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1658		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1659		VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1660	}
1661
1662	// Read back the result
1663	{
1664		const VkDeviceSize								imageSizeBytes				= (VkDeviceSize)(sizeof(deUint32) * m_renderSize.x() * m_renderSize.y());
1665		const VkBufferCreateInfo						readImageBufferParams		=
1666		{
1667			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//  VkStructureType		sType;
1668			DE_NULL,									//  const void*			pNext;
1669			0u,											//  VkBufferCreateFlags	flags;
1670			imageSizeBytes,								//  VkDeviceSize		size;
1671			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//  VkBufferUsageFlags	usage;
1672			VK_SHARING_MODE_EXCLUSIVE,					//  VkSharingMode		sharingMode;
1673			1u,											//  deUint32			queueFamilyCount;
1674			&queueFamilyIndex,							//  const deUint32*		pQueueFamilyIndices;
1675		};
1676		const Unique<VkBuffer>							readImageBuffer				(createBuffer(vk, vkDevice, &readImageBufferParams));
1677		const de::UniquePtr<Allocation>					readImageBufferMemory		(m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
1678
1679		VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
1680
1681		// Copy image to buffer
1682		const VkCommandBufferAllocateInfo				cmdBufferParams				=
1683		{
1684			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1685			DE_NULL,										// const void*				pNext;
1686			*m_cmdPool,										// VkCmdPool				cmdPool;
1687			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
1688			1u												// deUint32					bufferCount;
1689		};
1690
1691		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
1692		{
1693			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
1694			DE_NULL,										// const void*				pNext;
1695			0u,												// VkCmdBufferOptimizeFlags	flags;
1696			DE_NULL,										// VkRenderPass				renderPass;
1697			0u,												// deUint32					subpass;
1698			DE_NULL,										// VkFramebuffer			framebuffer;
1699			VK_FALSE,
1700			(VkQueryControlFlags)0,
1701			(VkQueryPipelineStatisticFlags)0,
1702		};
1703
1704		const Move<VkCommandBuffer>						cmdBuffer					= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1705
1706		const VkBufferImageCopy							copyParams					=
1707		{
1708			0u,											// VkDeviceSize			bufferOffset;
1709			(deUint32)m_renderSize.x(),					// deUint32				bufferRowLength;
1710			(deUint32)m_renderSize.y(),					// deUint32				bufferImageHeight;
1711			{
1712				VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspect		aspect;
1713				0u,									// deUint32				mipLevel;
1714				0u,									// deUint32				arraySlice;
1715				1u,									// deUint32				arraySize;
1716			},											// VkImageSubresourceCopy	imageSubresource;
1717			{ 0u, 0u, 0u },								// VkOffset3D			imageOffset;
1718			{ m_renderSize.x(), m_renderSize.y(), 1u }	// VkExtent3D			imageExtent;
1719		};
1720		const VkSubmitInfo								submitInfo					=
1721		{
1722			VK_STRUCTURE_TYPE_SUBMIT_INFO,
1723			DE_NULL,
1724			0u,
1725			(const VkSemaphore*)DE_NULL,
1726			1u,
1727			&cmdBuffer.get(),
1728			0u,
1729			(const VkSemaphore*)DE_NULL,
1730		};
1731
1732		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1733		vk.cmdCopyImageToBuffer(*cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
1734		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1735
1736		VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1737		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1738		VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1739
1740		invalidateMappedMemoryRange(vk, vkDevice, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset(), imageSizeBytes);
1741
1742		const tcu::TextureFormat						resultFormat				(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1743		const tcu::ConstPixelBufferAccess				resultAccess				(resultFormat, m_renderSize.x(), m_renderSize.y(), 1, readImageBufferMemory->getHostPtr());
1744
1745		tcu::copy(result.getAccess(), resultAccess);
1746	}
1747}
1748
1749void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
1750{
1751	// Buffer info.
1752	const int				width		= result.getWidth();
1753	const int				height		= result.getHeight();
1754	const int				gridSize	= quadGrid.getGridSize();
1755	const int				stride		= gridSize + 1;
1756	const bool				hasAlpha	= true; // \todo [2015-09-07 elecro] add correct alpha check
1757	ShaderEvalContext		evalCtx		(quadGrid);
1758
1759	// Evaluate color for each vertex.
1760	std::vector<tcu::Vec4>	colors		((gridSize + 1) * (gridSize + 1));
1761	for (int y = 0; y < gridSize+1; y++)
1762	for (int x = 0; x < gridSize+1; x++)
1763	{
1764		const float	sx			= (float)x / (float)gridSize;
1765		const float	sy			= (float)y / (float)gridSize;
1766		const int	vtxNdx		= ((y * (gridSize+1)) + x);
1767
1768		evalCtx.reset(sx, sy);
1769		m_evaluator.evaluate(evalCtx);
1770		DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
1771		tcu::Vec4 color = evalCtx.color;
1772
1773		if (!hasAlpha)
1774			color.w() = 1.0f;
1775
1776		colors[vtxNdx] = color;
1777	}
1778
1779	// Render quads.
1780	for (int y = 0; y < gridSize; y++)
1781	for (int x = 0; x < gridSize; x++)
1782	{
1783		const float		x0		= (float)x       / (float)gridSize;
1784		const float		x1		= (float)(x + 1) / (float)gridSize;
1785		const float		y0		= (float)y       / (float)gridSize;
1786		const float		y1		= (float)(y + 1) / (float)gridSize;
1787
1788		const float		sx0		= x0 * (float)width;
1789		const float		sx1		= x1 * (float)width;
1790		const float		sy0		= y0 * (float)height;
1791		const float		sy1		= y1 * (float)height;
1792		const float		oosx	= 1.0f / (sx1 - sx0);
1793		const float		oosy	= 1.0f / (sy1 - sy0);
1794
1795		const int		ix0		= deCeilFloatToInt32(sx0 - 0.5f);
1796		const int		ix1		= deCeilFloatToInt32(sx1 - 0.5f);
1797		const int		iy0		= deCeilFloatToInt32(sy0 - 0.5f);
1798		const int		iy1		= deCeilFloatToInt32(sy1 - 0.5f);
1799
1800		const int		v00		= (y * stride) + x;
1801		const int		v01		= (y * stride) + x + 1;
1802		const int		v10		= ((y + 1) * stride) + x;
1803		const int		v11		= ((y + 1) * stride) + x + 1;
1804		const tcu::Vec4	c00		= colors[v00];
1805		const tcu::Vec4	c01		= colors[v01];
1806		const tcu::Vec4	c10		= colors[v10];
1807		const tcu::Vec4	c11		= colors[v11];
1808
1809		//printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
1810
1811		for (int iy = iy0; iy < iy1; iy++)
1812		for (int ix = ix0; ix < ix1; ix++)
1813		{
1814			DE_ASSERT(deInBounds32(ix, 0, width));
1815			DE_ASSERT(deInBounds32(iy, 0, height));
1816
1817			const float			sfx		= (float)ix + 0.5f;
1818			const float			sfy		= (float)iy + 0.5f;
1819			const float			fx1		= deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
1820			const float			fy1		= deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
1821
1822			// Triangle quad interpolation.
1823			const bool			tri		= fx1 + fy1 <= 1.0f;
1824			const float			tx		= tri ? fx1 : (1.0f-fx1);
1825			const float			ty		= tri ? fy1 : (1.0f-fy1);
1826			const tcu::Vec4&	t0		= tri ? c00 : c11;
1827			const tcu::Vec4&	t1		= tri ? c01 : c10;
1828			const tcu::Vec4&	t2		= tri ? c10 : c01;
1829			const tcu::Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
1830
1831			result.setPixel(ix, iy, tcu::RGBA(color));
1832		}
1833	}
1834}
1835
1836void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
1837{
1838	// Buffer info.
1839	const int			width		= result.getWidth();
1840	const int			height		= result.getHeight();
1841	const bool			hasAlpha	= true;  // \todo [2015-09-07 elecro] add correct alpha check
1842	ShaderEvalContext	evalCtx		(quadGrid);
1843
1844	// Render.
1845	for (int y = 0; y < height; y++)
1846	for (int x = 0; x < width; x++)
1847	{
1848		const float sx = ((float)x + 0.5f) / (float)width;
1849		const float sy = ((float)y + 0.5f) / (float)height;
1850
1851		evalCtx.reset(sx, sy);
1852		m_evaluator.evaluate(evalCtx);
1853		// Select either clear color or computed color based on discarded bit.
1854		tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
1855
1856		if (!hasAlpha)
1857			color.w() = 1.0f;
1858
1859		result.setPixel(x, y, tcu::RGBA(color));
1860	}
1861}
1862
1863bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
1864{
1865	return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_RESULT);
1866}
1867
1868} // sr
1869} // vkt
1870