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 
51 namespace vkt
52 {
53 namespace sr
54 {
55 
56 using namespace vk;
57 
58 namespace
59 {
60 
61 static const int		GRID_SIZE			= 2;
62 static const deUint32	MAX_RENDER_WIDTH	= 128;
63 static const deUint32	MAX_RENDER_HEIGHT	= 128;
64 static const tcu::Vec4	DEFAULT_CLEAR_COLOR	= tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
65 
isSupportedLinearTilingFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)66 static 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 
isSupportedOptimalTilingFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)75 static 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 
createImageMemoryBarrier(const VkImage & image,VkAccessFlags srcAccessMask,VkAccessFlags dstAccessMask,VkImageLayout oldLayout,VkImageLayout newLayout)84 static 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 
116 class QuadGrid
117 {
118 public:
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 
getGridSize(void) const127 	int										getGridSize				(void) const { return m_gridSize; }
getNumVertices(void) const128 	int										getNumVertices			(void) const { return m_numVertices; }
getNumTriangles(void) const129 	int										getNumTriangles			(void) const { return m_numTriangles; }
getConstCoords(void) const130 	const tcu::Vec4&						getConstCoords			(void) const { return m_constCoords; }
getUserAttribTransforms(void) const131 	const std::vector<tcu::Mat4>			getUserAttribTransforms	(void) const { return m_userAttribTransforms; }
getTextures(void) const132 	const std::vector<TextureBindingSp>&	getTextures				(void) const { return m_textures; }
133 
getPositions(void) const134 	const tcu::Vec4*						getPositions			(void) const { return &m_positions[0]; }
getAttribOne(void) const135 	const float*							getAttribOne			(void) const { return &m_attribOne[0]; }
getCoords(void) const136 	const tcu::Vec4*						getCoords				(void) const { return &m_coords[0]; }
getUnitCoords(void) const137 	const tcu::Vec4*						getUnitCoords			(void) const { return &m_unitCoords[0]; }
138 
getUserAttrib(int attribNdx) const139 	const tcu::Vec4*						getUserAttrib			(int attribNdx) const { return &m_userAttribs[attribNdx][0]; }
getIndices(void) const140 	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 
getNumUserAttribs(void) const145 	int										getNumUserAttribs		(void) const { return (int)m_userAttribTransforms.size(); }
146 	tcu::Vec4								getUserAttrib			(int attribNdx, float sx, float sy) const;
147 
148 private:
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 
QuadGrid(int gridSize,int width,int height,const tcu::Vec4 & constCoords,const std::vector<tcu::Mat4> & userAttribTransforms,const std::vector<TextureBindingSp> & textures)166 QuadGrid::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 
~QuadGrid(void)234 QuadGrid::~QuadGrid (void)
235 {
236 }
237 
getCoords(float sx,float sy) const238 inline 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 
getUnitCoords(float sx,float sy) const245 inline 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 
getUserAttrib(int attribNdx,float sx,float sy) const250 inline 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 
TextureBinding(const tcu::Archive & archive,const char * filename,const Type type,const tcu::Sampler & sampler)258 TextureBinding::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 
~TextureBinding(void)273 TextureBinding::~TextureBinding (void)
274 {
275 	switch(m_type)
276 	{
277 		case TYPE_2D: delete m_binding.tex2D; break;
278 		default: break;
279 	}
280 }
281 
282 
loadTexture2D(const tcu::Archive & archive,const char * filename)283 de::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 
ShaderEvalContext(const QuadGrid & quadGrid)303 ShaderEvalContext::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 
~ShaderEvalContext(void)336 ShaderEvalContext::~ShaderEvalContext (void)
337 {
338 }
339 
reset(float sx,float sy)340 void 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 
texture2D(int unitNdx,const tcu::Vec2 & texCoords)357 tcu::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 
ShaderEvaluator(void)367 ShaderEvaluator::ShaderEvaluator (void)
368 	: m_evalFunc(DE_NULL)
369 {
370 }
371 
ShaderEvaluator(ShaderEvalFunc evalFunc)372 ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
373 	: m_evalFunc(evalFunc)
374 {
375 }
376 
~ShaderEvaluator(void)377 ShaderEvaluator::~ShaderEvaluator (void)
378 {
379 }
380 
evaluate(ShaderEvalContext & ctx) const381 void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
382 {
383 	DE_ASSERT(m_evalFunc);
384 	m_evalFunc(ctx);
385 }
386 
387 // UniformSetup.
388 
UniformSetup(void)389 UniformSetup::UniformSetup (void)
390 	: m_setupFunc(DE_NULL)
391 {
392 }
393 
UniformSetup(UniformSetupFunc setupFunc)394 UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
395 	: m_setupFunc(setupFunc)
396 {
397 }
398 
~UniformSetup(void)399 UniformSetup::~UniformSetup (void)
400 {
401 }
402 
setup(ShaderRenderCaseInstance & instance,const tcu::Vec4 & constCoords) const403 void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
404 {
405 	if (m_setupFunc)
406 		m_setupFunc(instance, constCoords);
407 }
408 
409 // ShaderRenderCase.
410 
ShaderRenderCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const bool isVertexCase,const ShaderEvalFunc evalFunc,const UniformSetup * uniformSetup,const AttributeSetupFunc attribFunc)411 ShaderRenderCase::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 
ShaderRenderCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const bool isVertexCase,const ShaderEvaluator * evaluator,const UniformSetup * uniformSetup,const AttributeSetupFunc attribFunc)425 ShaderRenderCase::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 
~ShaderRenderCase(void)439 ShaderRenderCase::~ShaderRenderCase (void)
440 {
441 }
442 
initPrograms(vk::SourceCollections & programCollection) const443 void 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 
createInstance(Context & context) const449 TestInstance* 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 
ShaderRenderCaseInstance(Context & context,const bool isVertexCase,const ShaderEvaluator & evaluator,const UniformSetup & uniformSetup,const AttributeSetupFunc attribFunc)458 ShaderRenderCaseInstance::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 
~ShaderRenderCaseInstance(void)475 ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
476 {
477 }
478 
iterate(void)479 tcu::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 
setupUniformData(deUint32 bindingLocation,size_t size,const void * dataPtr)510 void 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 
addUniform(deUint32 bindingLocation,vk::VkDescriptorType descriptorType,size_t dataSize,const void * data)545 void 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 
addAttribute(deUint32 bindingLocation,vk::VkFormat format,deUint32 sizePerElement,deUint32 count,const void * dataPtr)553 void 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 
useAttribute(deUint32 bindingLocation,BaseAttributeType type)610 void 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 
setup(void)620 void ShaderRenderCaseInstance::setup (void)
621 {
622 }
623 
setupUniforms(const tcu::Vec4 & constCoords)624 void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
625 {
626 	m_uniformSetup.setup(*this, constCoords);
627 }
628 
useUniform(deUint32 bindingLocation,BaseUniformType type)629 void 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 
getViewportSize(void) const740 const 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 
createImage2D(const tcu::Texture2D & texture,const VkFormat format,const VkImageUsageFlags usage,const VkImageTiling tiling)746 Move<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 
uploadImage2D(const tcu::Texture2D & refTexture,const VkImage & vkTexture)782 de::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 
copyTilingImageToOptimal(const vk::VkImage & srcImage,const vk::VkImage & dstImage,deUint32 width,deUint32 height)811 void 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 
useSampler2D(deUint32 bindingLocation,deUint32 textureID)939 void 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 
setupDefaultInputs(const QuadGrid & quadGrid)1029 void 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 
render(tcu::Surface & result,const QuadGrid & quadGrid)1100 void 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 
computeVertexReference(tcu::Surface & result,const QuadGrid & quadGrid)1739 void 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 
computeFragmentReference(tcu::Surface & result,const QuadGrid & quadGrid)1826 void 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 
compareImages(const tcu::Surface & resImage,const tcu::Surface & refImage,float errorThreshold)1853 bool 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