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