• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "vkCmdUtil.hpp"
48 #include "vkObjUtil.hpp"
49 
50 #include <vector>
51 #include <string>
52 
53 namespace vkt
54 {
55 namespace sr
56 {
57 
58 using namespace vk;
59 
60 namespace
61 {
62 
63 static const deUint32	MAX_RENDER_WIDTH	= 128;
64 static const deUint32	MAX_RENDER_HEIGHT	= 128;
65 static const tcu::Vec4	DEFAULT_CLEAR_COLOR	= tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
66 
textureTypeToImageViewType(TextureBinding::Type type)67 static VkImageViewType textureTypeToImageViewType (TextureBinding::Type type)
68 {
69 	switch (type)
70 	{
71 		case TextureBinding::TYPE_1D:			return VK_IMAGE_VIEW_TYPE_1D;
72 		case TextureBinding::TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
73 		case TextureBinding::TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
74 		case TextureBinding::TYPE_CUBE_MAP:		return VK_IMAGE_VIEW_TYPE_CUBE;
75 		case TextureBinding::TYPE_1D_ARRAY:		return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
76 		case TextureBinding::TYPE_2D_ARRAY:		return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
77 		case TextureBinding::TYPE_CUBE_ARRAY:	return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
78 
79 		default:
80 			DE_FATAL("Impossible");
81 			return (VkImageViewType)0;
82 	}
83 }
84 
viewTypeToImageType(VkImageViewType type)85 static VkImageType viewTypeToImageType (VkImageViewType type)
86 {
87 	switch (type)
88 	{
89 		case VK_IMAGE_VIEW_TYPE_1D:
90 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:		return VK_IMAGE_TYPE_1D;
91 		case VK_IMAGE_VIEW_TYPE_2D:
92 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:		return VK_IMAGE_TYPE_2D;
93 		case VK_IMAGE_VIEW_TYPE_3D:				return VK_IMAGE_TYPE_3D;
94 		case VK_IMAGE_VIEW_TYPE_CUBE:
95 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:		return VK_IMAGE_TYPE_2D;
96 
97 		default:
98 			DE_FATAL("Impossible");
99 			return (VkImageType)0;
100 	}
101 }
102 
103 /*! Gets the next multiple of a given divisor */
getNextMultiple(deUint32 divisor,deUint32 value)104 static deUint32 getNextMultiple (deUint32 divisor, deUint32 value)
105 {
106 	if (value % divisor == 0)
107 	{
108 		return value;
109 	}
110 	return value + divisor - (value % divisor);
111 }
112 
113 /*! Gets the next value that is multiple of all given divisors */
getNextMultiple(const std::vector<deUint32> & divisors,deUint32 value)114 static deUint32 getNextMultiple (const std::vector<deUint32>& divisors, deUint32 value)
115 {
116 	deUint32	nextMultiple		= value;
117 	bool		nextMultipleFound	= false;
118 
119 	while (true)
120 	{
121 		nextMultipleFound = true;
122 
123 		for (size_t divNdx = 0; divNdx < divisors.size(); divNdx++)
124 			nextMultipleFound = nextMultipleFound && (nextMultiple % divisors[divNdx] == 0);
125 
126 		if (nextMultipleFound)
127 			break;
128 
129 		DE_ASSERT(nextMultiple < ~((deUint32)0u));
130 		nextMultiple = getNextMultiple(divisors[0], nextMultiple + 1);
131 	}
132 
133 	return nextMultiple;
134 }
135 
136 } // anonymous
137 
138 // QuadGrid.
139 
140 class QuadGrid
141 {
142 public:
143 											QuadGrid				(int									gridSize,
144 																	 int									screenWidth,
145 																	 int									screenHeight,
146 																	 const tcu::Vec4&						constCoords,
147 																	 const std::vector<tcu::Mat4>&			userAttribTransforms,
148 																	 const std::vector<TextureBindingSp>&	textures);
149 											~QuadGrid				(void);
150 
getGridSize(void) const151 	int										getGridSize				(void) const { return m_gridSize; }
getNumVertices(void) const152 	int										getNumVertices			(void) const { return m_numVertices; }
getNumTriangles(void) const153 	int										getNumTriangles			(void) const { return m_numTriangles; }
getConstCoords(void) const154 	const tcu::Vec4&						getConstCoords			(void) const { return m_constCoords; }
getUserAttribTransforms(void) const155 	const std::vector<tcu::Mat4>			getUserAttribTransforms	(void) const { return m_userAttribTransforms; }
getTextures(void) const156 	const std::vector<TextureBindingSp>&	getTextures				(void) const { return m_textures; }
157 
getPositions(void) const158 	const tcu::Vec4*						getPositions			(void) const { return &m_positions[0]; }
getAttribOne(void) const159 	const float*							getAttribOne			(void) const { return &m_attribOne[0]; }
getCoords(void) const160 	const tcu::Vec4*						getCoords				(void) const { return &m_coords[0]; }
getUnitCoords(void) const161 	const tcu::Vec4*						getUnitCoords			(void) const { return &m_unitCoords[0]; }
162 
getUserAttrib(int attribNdx) const163 	const tcu::Vec4*						getUserAttrib			(int attribNdx) const { return &m_userAttribs[attribNdx][0]; }
getIndices(void) const164 	const deUint16*							getIndices				(void) const { return &m_indices[0]; }
165 
166 	tcu::Vec4								getCoords				(float sx, float sy) const;
167 	tcu::Vec4								getUnitCoords			(float sx, float sy) const;
168 
getNumUserAttribs(void) const169 	int										getNumUserAttribs		(void) const { return (int)m_userAttribTransforms.size(); }
170 	tcu::Vec4								getUserAttrib			(int attribNdx, float sx, float sy) const;
171 
172 private:
173 	const int								m_gridSize;
174 	const int								m_numVertices;
175 	const int								m_numTriangles;
176 	const tcu::Vec4							m_constCoords;
177 	const std::vector<tcu::Mat4>			m_userAttribTransforms;
178 
179 	const std::vector<TextureBindingSp>&	m_textures;
180 
181 	std::vector<tcu::Vec4>					m_screenPos;
182 	std::vector<tcu::Vec4>					m_positions;
183 	std::vector<tcu::Vec4>					m_coords;		//!< Near-unit coordinates, roughly [-2.0 .. 2.0].
184 	std::vector<tcu::Vec4>					m_unitCoords;	//!< Positive-only coordinates [0.0 .. 1.5].
185 	std::vector<float>						m_attribOne;
186 	std::vector<tcu::Vec4>					m_userAttribs[ShaderEvalContext::MAX_TEXTURES];
187 	std::vector<deUint16>					m_indices;
188 };
189 
QuadGrid(int gridSize,int width,int height,const tcu::Vec4 & constCoords,const std::vector<tcu::Mat4> & userAttribTransforms,const std::vector<TextureBindingSp> & textures)190 QuadGrid::QuadGrid (int										gridSize,
191 					int										width,
192 					int										height,
193 					const tcu::Vec4&						constCoords,
194 					const std::vector<tcu::Mat4>&			userAttribTransforms,
195 					const std::vector<TextureBindingSp>&	textures)
196 	: m_gridSize				(gridSize)
197 	, m_numVertices				((gridSize + 1) * (gridSize + 1))
198 	, m_numTriangles			(gridSize * gridSize * 2)
199 	, m_constCoords				(constCoords)
200 	, m_userAttribTransforms	(userAttribTransforms)
201 	, m_textures				(textures)
202 {
203 	const tcu::Vec4 viewportScale	((float)width, (float)height, 0.0f, 0.0f);
204 
205 	// Compute vertices.
206 	m_screenPos.resize(m_numVertices);
207 	m_positions.resize(m_numVertices);
208 	m_coords.resize(m_numVertices);
209 	m_unitCoords.resize(m_numVertices);
210 	m_attribOne.resize(m_numVertices);
211 
212 	// User attributes.
213 	for (int attrNdx = 0; attrNdx < DE_LENGTH_OF_ARRAY(m_userAttribs); attrNdx++)
214 		m_userAttribs[attrNdx].resize(m_numVertices);
215 
216 	for (int y = 0; y < gridSize+1; y++)
217 	for (int x = 0; x < gridSize+1; x++)
218 	{
219 		float		sx			= (float)x / (float)gridSize;
220 		float		sy			= (float)y / (float)gridSize;
221 		float		fx			= 2.0f * sx - 1.0f;
222 		float		fy			= 2.0f * sy - 1.0f;
223 		int			vtxNdx		= ((y * (gridSize+1)) + x);
224 
225 		m_positions[vtxNdx]		= tcu::Vec4(fx, fy, 0.0f, 1.0f);
226 		m_coords[vtxNdx]		= getCoords(sx, sy);
227 		m_unitCoords[vtxNdx]	= getUnitCoords(sx, sy);
228 		m_attribOne[vtxNdx]		= 1.0f;
229 
230 		m_screenPos[vtxNdx]		= tcu::Vec4(sx, sy, 0.0f, 1.0f) * viewportScale;
231 
232 		for (int attribNdx = 0; attribNdx < getNumUserAttribs(); attribNdx++)
233 			m_userAttribs[attribNdx][vtxNdx] = getUserAttrib(attribNdx, sx, sy);
234 	}
235 
236 	// Compute indices.
237 	m_indices.resize(3 * m_numTriangles);
238 	for (int y = 0; y < gridSize; y++)
239 	for (int x = 0; x < gridSize; x++)
240 	{
241 		int stride				= gridSize + 1;
242 		int v00					= (y * stride) + x;
243 		int v01					= (y * stride) + x + 1;
244 		int v10					= ((y+1) * stride) + x;
245 		int v11					= ((y+1) * stride) + x + 1;
246 
247 		int baseNdx				= ((y * gridSize) + x) * 6;
248 		m_indices[baseNdx + 0]	= (deUint16)v10;
249 		m_indices[baseNdx + 1]	= (deUint16)v00;
250 		m_indices[baseNdx + 2]	= (deUint16)v01;
251 
252 		m_indices[baseNdx + 3]	= (deUint16)v10;
253 		m_indices[baseNdx + 4]	= (deUint16)v01;
254 		m_indices[baseNdx + 5]	= (deUint16)v11;
255 	}
256 }
257 
~QuadGrid(void)258 QuadGrid::~QuadGrid (void)
259 {
260 }
261 
getCoords(float sx,float sy) const262 inline tcu::Vec4 QuadGrid::getCoords (float sx, float sy) const
263 {
264 	const float fx = 2.0f * sx - 1.0f;
265 	const float fy = 2.0f * sy - 1.0f;
266 	return tcu::Vec4(fx, fy, -fx + 0.33f*fy, -0.275f*fx - fy);
267 }
268 
getUnitCoords(float sx,float sy) const269 inline tcu::Vec4 QuadGrid::getUnitCoords (float sx, float sy) const
270 {
271 	return tcu::Vec4(sx, sy, 0.33f*sx + 0.5f*sy, 0.5f*sx + 0.25f*sy);
272 }
273 
getUserAttrib(int attribNdx,float sx,float sy) const274 inline tcu::Vec4 QuadGrid::getUserAttrib (int attribNdx, float sx, float sy) const
275 {
276 	// homogeneous normalized screen-space coordinates
277 	return m_userAttribTransforms[attribNdx] * tcu::Vec4(sx, sy, 0.0f, 1.0f);
278 }
279 
280 // TextureBinding
281 
TextureBinding(const tcu::Archive & archive,const char * filename,const Type type,const tcu::Sampler & sampler)282 TextureBinding::TextureBinding (const tcu::Archive&	archive,
283 								const char*			filename,
284 								const Type			type,
285 								const tcu::Sampler&	sampler)
286 	: m_type	(type)
287 	, m_sampler	(sampler)
288 {
289 	switch(m_type)
290 	{
291 		case TYPE_2D: m_binding.tex2D = loadTexture2D(archive, filename).release(); break;
292 		default:
293 			DE_FATAL("Unsupported texture type");
294 	}
295 }
296 
TextureBinding(const tcu::Texture1D * tex1D,const tcu::Sampler & sampler)297 TextureBinding::TextureBinding (const tcu::Texture1D* tex1D, const tcu::Sampler& sampler)
298 	: m_type	(TYPE_1D)
299 	, m_sampler	(sampler)
300 {
301 	m_binding.tex1D = tex1D;
302 }
303 
TextureBinding(const tcu::Texture2D * tex2D,const tcu::Sampler & sampler)304 TextureBinding::TextureBinding (const tcu::Texture2D* tex2D, const tcu::Sampler& sampler)
305 	: m_type	(TYPE_2D)
306 	, m_sampler	(sampler)
307 {
308 	m_binding.tex2D = tex2D;
309 }
310 
TextureBinding(const tcu::Texture3D * tex3D,const tcu::Sampler & sampler)311 TextureBinding::TextureBinding (const tcu::Texture3D* tex3D, const tcu::Sampler& sampler)
312 	: m_type	(TYPE_3D)
313 	, m_sampler	(sampler)
314 {
315 	m_binding.tex3D = tex3D;
316 }
317 
TextureBinding(const tcu::TextureCube * texCube,const tcu::Sampler & sampler)318 TextureBinding::TextureBinding (const tcu::TextureCube* texCube, const tcu::Sampler& sampler)
319 	: m_type	(TYPE_CUBE_MAP)
320 	, m_sampler	(sampler)
321 {
322 	m_binding.texCube = texCube;
323 }
324 
TextureBinding(const tcu::Texture1DArray * tex1DArray,const tcu::Sampler & sampler)325 TextureBinding::TextureBinding (const tcu::Texture1DArray* tex1DArray, const tcu::Sampler& sampler)
326 	: m_type	(TYPE_1D_ARRAY)
327 	, m_sampler	(sampler)
328 {
329 	m_binding.tex1DArray = tex1DArray;
330 }
331 
TextureBinding(const tcu::Texture2DArray * tex2DArray,const tcu::Sampler & sampler)332 TextureBinding::TextureBinding (const tcu::Texture2DArray* tex2DArray, const tcu::Sampler& sampler)
333 	: m_type	(TYPE_2D_ARRAY)
334 	, m_sampler	(sampler)
335 {
336 	m_binding.tex2DArray = tex2DArray;
337 }
338 
TextureBinding(const tcu::TextureCubeArray * texCubeArray,const tcu::Sampler & sampler)339 TextureBinding::TextureBinding (const tcu::TextureCubeArray* texCubeArray, const tcu::Sampler& sampler)
340 	: m_type	(TYPE_CUBE_ARRAY)
341 	, m_sampler	(sampler)
342 {
343 	m_binding.texCubeArray = texCubeArray;
344 }
345 
~TextureBinding(void)346 TextureBinding::~TextureBinding (void)
347 {
348 	switch(m_type)
349 	{
350 		case TYPE_1D:			delete m_binding.tex1D;			break;
351 		case TYPE_2D:			delete m_binding.tex2D;			break;
352 		case TYPE_3D:			delete m_binding.tex3D;			break;
353 		case TYPE_CUBE_MAP:		delete m_binding.texCube;		break;
354 		case TYPE_1D_ARRAY:		delete m_binding.tex1DArray;	break;
355 		case TYPE_2D_ARRAY:		delete m_binding.tex2DArray;	break;
356 		case TYPE_CUBE_ARRAY:	delete m_binding.texCubeArray;	break;
357 		default:												break;
358 	}
359 }
360 
loadTexture2D(const tcu::Archive & archive,const char * filename)361 de::MovePtr<tcu::Texture2D> TextureBinding::loadTexture2D (const tcu::Archive& archive, const char* filename)
362 {
363 	tcu::TextureLevel level;
364 	tcu::ImageIO::loadImage(level, archive, filename);
365 
366 	TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
367 					   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
368 
369 	// \todo [2015-10-08 elecro] for some reason we get better when using RGBA texture even in RGB case, this needs to be investigated
370 	de::MovePtr<tcu::Texture2D> texture(new tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth(), level.getHeight()));
371 
372 	// Fill level 0.
373 	texture->allocLevel(0);
374 	tcu::copy(texture->getLevel(0), level.getAccess());
375 
376 	return texture;
377 }
378 
379 // ShaderEvalContext.
380 
ShaderEvalContext(const QuadGrid & quadGrid)381 ShaderEvalContext::ShaderEvalContext (const QuadGrid& quadGrid)
382 	: constCoords	(quadGrid.getConstCoords())
383 	, isDiscarded	(false)
384 	, m_quadGrid	(quadGrid)
385 {
386 	const std::vector<TextureBindingSp>& bindings = m_quadGrid.getTextures();
387 	DE_ASSERT((int)bindings.size() <= MAX_TEXTURES);
388 
389 	// Fill in texture array.
390 	for (int ndx = 0; ndx < (int)bindings.size(); ndx++)
391 	{
392 		const TextureBinding& binding = *bindings[ndx];
393 
394 		if (binding.getType() == TextureBinding::TYPE_NONE)
395 			continue;
396 
397 		textures[ndx].sampler = binding.getSampler();
398 
399 		switch (binding.getType())
400 		{
401 			case TextureBinding::TYPE_1D:			textures[ndx].tex1D			= &binding.get1D();			break;
402 			case TextureBinding::TYPE_2D:			textures[ndx].tex2D			= &binding.get2D();			break;
403 			case TextureBinding::TYPE_3D:			textures[ndx].tex3D			= &binding.get3D();			break;
404 			case TextureBinding::TYPE_CUBE_MAP:		textures[ndx].texCube		= &binding.getCube();		break;
405 			case TextureBinding::TYPE_1D_ARRAY:		textures[ndx].tex1DArray	= &binding.get1DArray();	break;
406 			case TextureBinding::TYPE_2D_ARRAY:		textures[ndx].tex2DArray	= &binding.get2DArray();	break;
407 			case TextureBinding::TYPE_CUBE_ARRAY:	textures[ndx].texCubeArray	= &binding.getCubeArray();	break;
408 			default:
409 				TCU_THROW(InternalError, "Handling of texture binding type not implemented");
410 		}
411 	}
412 }
413 
~ShaderEvalContext(void)414 ShaderEvalContext::~ShaderEvalContext (void)
415 {
416 }
417 
reset(float sx,float sy)418 void ShaderEvalContext::reset (float sx, float sy)
419 {
420 	// Clear old values
421 	color		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
422 	isDiscarded	= false;
423 
424 	// Compute coords
425 	coords		= m_quadGrid.getCoords(sx, sy);
426 	unitCoords	= m_quadGrid.getUnitCoords(sx, sy);
427 
428 	// Compute user attributes.
429 	const int numAttribs = m_quadGrid.getNumUserAttribs();
430 	DE_ASSERT(numAttribs <= MAX_USER_ATTRIBS);
431 	for (int attribNdx = 0; attribNdx < numAttribs; attribNdx++)
432 		in[attribNdx] = m_quadGrid.getUserAttrib(attribNdx, sx, sy);
433 }
434 
texture2D(int unitNdx,const tcu::Vec2 & texCoords)435 tcu::Vec4 ShaderEvalContext::texture2D (int unitNdx, const tcu::Vec2& texCoords)
436 {
437 	if (textures[unitNdx].tex2D)
438 		return textures[unitNdx].tex2D->sample(textures[unitNdx].sampler, texCoords.x(), texCoords.y(), 0.0f);
439 	else
440 		return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
441 }
442 
443 // ShaderEvaluator.
444 
ShaderEvaluator(void)445 ShaderEvaluator::ShaderEvaluator (void)
446 	: m_evalFunc(DE_NULL)
447 {
448 }
449 
ShaderEvaluator(ShaderEvalFunc evalFunc)450 ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
451 	: m_evalFunc(evalFunc)
452 {
453 }
454 
~ShaderEvaluator(void)455 ShaderEvaluator::~ShaderEvaluator (void)
456 {
457 }
458 
evaluate(ShaderEvalContext & ctx) const459 void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
460 {
461 	DE_ASSERT(m_evalFunc);
462 	m_evalFunc(ctx);
463 }
464 
465 // UniformSetup.
466 
UniformSetup(void)467 UniformSetup::UniformSetup (void)
468 	: m_setupFunc(DE_NULL)
469 {
470 }
471 
UniformSetup(UniformSetupFunc setupFunc)472 UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
473 	: m_setupFunc(setupFunc)
474 {
475 }
476 
~UniformSetup(void)477 UniformSetup::~UniformSetup (void)
478 {
479 }
480 
setup(ShaderRenderCaseInstance & instance,const tcu::Vec4 & constCoords) const481 void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
482 {
483 	if (m_setupFunc)
484 		m_setupFunc(instance, constCoords);
485 }
486 
487 // ShaderRenderCase.
488 
ShaderRenderCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const bool isVertexCase,const ShaderEvalFunc evalFunc,const UniformSetup * uniformSetup,const AttributeSetupFunc attribFunc)489 ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
490 									const std::string&			name,
491 									const std::string&			description,
492 									const bool					isVertexCase,
493 									const ShaderEvalFunc		evalFunc,
494 									const UniformSetup*			uniformSetup,
495 									const AttributeSetupFunc	attribFunc)
496 	: vkt::TestCase		(testCtx, name, description)
497 	, m_isVertexCase	(isVertexCase)
498 	, m_evaluator		(new ShaderEvaluator(evalFunc))
499 	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
500 	, m_attribFunc		(attribFunc)
501 {}
502 
ShaderRenderCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const bool isVertexCase,const ShaderEvaluator * evaluator,const UniformSetup * uniformSetup,const AttributeSetupFunc attribFunc)503 ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
504 									const std::string&			name,
505 									const std::string&			description,
506 									const bool					isVertexCase,
507 									const ShaderEvaluator*		evaluator,
508 									const UniformSetup*			uniformSetup,
509 									const AttributeSetupFunc	attribFunc)
510 	: vkt::TestCase		(testCtx, name, description)
511 	, m_isVertexCase	(isVertexCase)
512 	, m_evaluator		(evaluator)
513 	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
514 	, m_attribFunc		(attribFunc)
515 {}
516 
~ShaderRenderCase(void)517 ShaderRenderCase::~ShaderRenderCase (void)
518 {
519 }
520 
initPrograms(vk::SourceCollections & programCollection) const521 void ShaderRenderCase::initPrograms (vk::SourceCollections& programCollection) const
522 {
523 	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
524 	programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
525 }
526 
createInstance(Context & context) const527 TestInstance* ShaderRenderCase::createInstance (Context& context) const
528 {
529 	DE_ASSERT(m_evaluator != DE_NULL);
530 	DE_ASSERT(m_uniformSetup != DE_NULL);
531 	return new ShaderRenderCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_attribFunc);
532 }
533 
534 // ShaderRenderCaseInstance.
535 
ShaderRenderCaseInstance(Context & context)536 ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context& context)
537 	: vkt::TestInstance		(context)
538 	, m_imageBackingMode	(IMAGE_BACKING_MODE_REGULAR)
539 	, m_quadGridSize		(static_cast<deUint32>(GRID_SIZE_DEFAULT_FRAGMENT))
540 	, m_memAlloc			(getAllocator())
541 	, m_clearColor			(DEFAULT_CLEAR_COLOR)
542 	, m_isVertexCase		(false)
543 	, m_vertexShaderName	("vert")
544 	, m_fragmentShaderName	("frag")
545 	, m_renderSize			(MAX_RENDER_WIDTH, MAX_RENDER_HEIGHT)
546 	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
547 	, m_evaluator			(DE_NULL)
548 	, m_uniformSetup		(DE_NULL)
549 	, m_attribFunc			(DE_NULL)
550 	, m_sampleCount			(VK_SAMPLE_COUNT_1_BIT)
551 {
552 }
553 
554 
ShaderRenderCaseInstance(Context & context,const bool isVertexCase,const ShaderEvaluator & evaluator,const UniformSetup & uniformSetup,const AttributeSetupFunc attribFunc,const ImageBackingMode imageBackingMode,const deUint32 gridSize)555 ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&					context,
556 													const bool					isVertexCase,
557 													const ShaderEvaluator&		evaluator,
558 													const UniformSetup&			uniformSetup,
559 													const AttributeSetupFunc	attribFunc,
560 													const ImageBackingMode		imageBackingMode,
561 													const deUint32				gridSize)
562 	: vkt::TestInstance		(context)
563 	, m_imageBackingMode	(imageBackingMode)
564 	, m_quadGridSize		(gridSize == static_cast<deUint32>(GRID_SIZE_DEFAULTS)
565 							 ? (isVertexCase
566 								? static_cast<deUint32>(GRID_SIZE_DEFAULT_VERTEX)
567 								: static_cast<deUint32>(GRID_SIZE_DEFAULT_FRAGMENT))
568 							 : gridSize)
569 	, m_memAlloc			(getAllocator())
570 	, m_clearColor			(DEFAULT_CLEAR_COLOR)
571 	, m_isVertexCase		(isVertexCase)
572 	, m_vertexShaderName	("vert")
573 	, m_fragmentShaderName	("frag")
574 	, m_renderSize			(MAX_RENDER_WIDTH, MAX_RENDER_HEIGHT)
575 	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
576 	, m_evaluator			(&evaluator)
577 	, m_uniformSetup		(&uniformSetup)
578 	, m_attribFunc			(attribFunc)
579 	, m_sampleCount			(VK_SAMPLE_COUNT_1_BIT)
580 {
581 }
582 
ShaderRenderCaseInstance(Context & context,const bool isVertexCase,const ShaderEvaluator * evaluator,const UniformSetup * uniformSetup,const AttributeSetupFunc attribFunc,const ImageBackingMode imageBackingMode,const deUint32 gridSize)583 ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&					context,
584 													const bool					isVertexCase,
585 													const ShaderEvaluator*		evaluator,
586 													const UniformSetup*			uniformSetup,
587 													const AttributeSetupFunc	attribFunc,
588 													const ImageBackingMode		imageBackingMode,
589 													const deUint32				gridSize)
590 	: vkt::TestInstance		(context)
591 	, m_imageBackingMode	(imageBackingMode)
592 	, m_quadGridSize		(gridSize == static_cast<deUint32>(GRID_SIZE_DEFAULTS)
593 							 ? (isVertexCase
594 								? static_cast<deUint32>(GRID_SIZE_DEFAULT_VERTEX)
595 								: static_cast<deUint32>(GRID_SIZE_DEFAULT_FRAGMENT))
596 							 : gridSize)
597 	, m_memAlloc			(getAllocator())
598 	, m_clearColor			(DEFAULT_CLEAR_COLOR)
599 	, m_isVertexCase		(isVertexCase)
600 	, m_vertexShaderName	("vert")
601 	, m_fragmentShaderName	("frag")
602 	, m_renderSize			(MAX_RENDER_WIDTH, MAX_RENDER_HEIGHT)
603 	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
604 	, m_evaluator			(evaluator)
605 	, m_uniformSetup		(uniformSetup)
606 	, m_attribFunc			(attribFunc)
607 	, m_sampleCount			(VK_SAMPLE_COUNT_1_BIT)
608 {
609 }
610 
getAllocator(void) const611 vk::Allocator& ShaderRenderCaseInstance::getAllocator (void) const
612 {
613 	return m_context.getDefaultAllocator();
614 }
615 
~ShaderRenderCaseInstance(void)616 ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
617 {
618 }
619 
getDevice(void) const620 VkDevice ShaderRenderCaseInstance::getDevice (void) const
621 {
622 	return m_context.getDevice();
623 }
624 
getUniversalQueueFamilyIndex(void) const625 deUint32 ShaderRenderCaseInstance::getUniversalQueueFamilyIndex	(void) const
626 {
627 	return m_context.getUniversalQueueFamilyIndex();
628 }
629 
getSparseQueueFamilyIndex(void) const630 deUint32 ShaderRenderCaseInstance::getSparseQueueFamilyIndex (void) const
631 {
632 	return m_context.getSparseQueueFamilyIndex();
633 }
634 
getDeviceInterface(void) const635 const DeviceInterface& ShaderRenderCaseInstance::getDeviceInterface (void) const
636 {
637 	return m_context.getDeviceInterface();
638 }
639 
getUniversalQueue(void) const640 VkQueue ShaderRenderCaseInstance::getUniversalQueue (void) const
641 {
642 	return m_context.getUniversalQueue();
643 }
644 
getSparseQueue(void) const645 VkQueue ShaderRenderCaseInstance::getSparseQueue (void) const
646 {
647 	return m_context.getSparseQueue();
648 }
649 
getPhysicalDevice(void) const650 VkPhysicalDevice ShaderRenderCaseInstance::getPhysicalDevice (void) const
651 {
652 	return m_context.getPhysicalDevice();
653 }
654 
getInstanceInterface(void) const655 const InstanceInterface& ShaderRenderCaseInstance::getInstanceInterface (void) const
656 {
657 	return m_context.getInstanceInterface();
658 }
659 
iterate(void)660 tcu::TestStatus ShaderRenderCaseInstance::iterate (void)
661 {
662 	setup();
663 
664 	// Create quad grid.
665 	const tcu::UVec2	viewportSize	= getViewportSize();
666 	const int			width			= viewportSize.x();
667 	const int			height			= viewportSize.y();
668 
669 	m_quadGrid							= de::MovePtr<QuadGrid>(new QuadGrid(m_quadGridSize, width, height, getDefaultConstCoords(), m_userAttribTransforms, m_textures));
670 
671 	// Render result.
672 	tcu::Surface		resImage		(width, height);
673 
674 	render(m_quadGrid->getNumVertices(), m_quadGrid->getNumTriangles(), m_quadGrid->getIndices(), m_quadGrid->getConstCoords());
675 	tcu::copy(resImage.getAccess(), m_resultImage.getAccess());
676 
677 	// Compute reference.
678 	tcu::Surface		refImage		(width, height);
679 	if (m_isVertexCase)
680 		computeVertexReference(refImage, *m_quadGrid);
681 	else
682 		computeFragmentReference(refImage, *m_quadGrid);
683 
684 	// Compare.
685 	const bool			compareOk		= compareImages(resImage, refImage, 0.2f);
686 
687 	if (compareOk)
688 		return tcu::TestStatus::pass("Result image matches reference");
689 	else
690 		return tcu::TestStatus::fail("Image mismatch");
691 }
692 
setup(void)693 void ShaderRenderCaseInstance::setup (void)
694 {
695 	m_resultImage					= tcu::TextureLevel();
696 	m_descriptorSetLayoutBuilder	= de::MovePtr<DescriptorSetLayoutBuilder>	(new DescriptorSetLayoutBuilder());
697 	m_descriptorPoolBuilder			= de::MovePtr<DescriptorPoolBuilder>		(new DescriptorPoolBuilder());
698 	m_descriptorSetUpdateBuilder	= de::MovePtr<DescriptorSetUpdateBuilder>	(new DescriptorSetUpdateBuilder());
699 
700 	m_uniformInfos.clear();
701 	m_vertexBindingDescription.clear();
702 	m_vertexAttributeDescription.clear();
703 	m_vertexBuffers.clear();
704 	m_vertexBufferAllocs.clear();
705 	m_pushConstantRanges.clear();
706 }
707 
setupUniformData(deUint32 bindingLocation,size_t size,const void * dataPtr)708 void ShaderRenderCaseInstance::setupUniformData (deUint32 bindingLocation, size_t size, const void* dataPtr)
709 {
710 	const VkDevice					vkDevice			= getDevice();
711 	const DeviceInterface&			vk					= getDeviceInterface();
712 	const deUint32					queueFamilyIndex	= getUniversalQueueFamilyIndex();
713 
714 	const VkBufferCreateInfo		uniformBufferParams	=
715 	{
716 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
717 		DE_NULL,									// const void*			pNext;
718 		0u,											// VkBufferCreateFlags	flags;
719 		size,										// VkDeviceSize			size;
720 		VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
721 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
722 		1u,											// deUint32				queueFamilyCount;
723 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
724 	};
725 
726 	Move<VkBuffer>					buffer				= createBuffer(vk, vkDevice, &uniformBufferParams);
727 	de::MovePtr<Allocation>			alloc				= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
728 	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
729 
730 	deMemcpy(alloc->getHostPtr(), dataPtr, size);
731 	flushAlloc(vk, vkDevice, *alloc);
732 
733 	de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
734 	uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
735 	uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size);
736 	uniformInfo->location = bindingLocation;
737 	uniformInfo->buffer = VkBufferSp(new vk::Unique<VkBuffer>(buffer));
738 	uniformInfo->alloc = AllocationSp(alloc.release());
739 
740 	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
741 }
742 
addUniform(deUint32 bindingLocation,vk::VkDescriptorType descriptorType,size_t dataSize,const void * data)743 void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, size_t dataSize, const void* data)
744 {
745 	m_descriptorSetLayoutBuilder->addSingleBinding(descriptorType, vk::VK_SHADER_STAGE_ALL);
746 	m_descriptorPoolBuilder->addType(descriptorType);
747 
748 	setupUniformData(bindingLocation, dataSize, data);
749 }
750 
addAttribute(deUint32 bindingLocation,vk::VkFormat format,deUint32 sizePerElement,deUint32 count,const void * dataPtr)751 void ShaderRenderCaseInstance::addAttribute (deUint32		bindingLocation,
752 											 vk::VkFormat	format,
753 											 deUint32		sizePerElement,
754 											 deUint32		count,
755 											 const void*	dataPtr)
756 {
757 	// Add binding specification
758 	const deUint32							binding					= (deUint32)m_vertexBindingDescription.size();
759 	const VkVertexInputBindingDescription	bindingDescription		=
760 	{
761 		binding,							// deUint32				binding;
762 		sizePerElement,						// deUint32				stride;
763 		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	stepRate;
764 	};
765 
766 	m_vertexBindingDescription.push_back(bindingDescription);
767 
768 	// Add location and format specification
769 	const VkVertexInputAttributeDescription	attributeDescription	=
770 	{
771 		bindingLocation,			// deUint32	location;
772 		binding,					// deUint32	binding;
773 		format,						// VkFormat	format;
774 		0u,							// deUint32	offset;
775 	};
776 
777 	m_vertexAttributeDescription.push_back(attributeDescription);
778 
779 	// Upload data to buffer
780 	const VkDevice							vkDevice				= getDevice();
781 	const DeviceInterface&					vk						= getDeviceInterface();
782 	const deUint32							queueFamilyIndex		= getUniversalQueueFamilyIndex();
783 
784 	const VkDeviceSize						inputSize				= sizePerElement * count;
785 	const VkBufferCreateInfo				vertexBufferParams		=
786 	{
787 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
788 		DE_NULL,									// const void*			pNext;
789 		0u,											// VkBufferCreateFlags	flags;
790 		inputSize,									// VkDeviceSize			size;
791 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
792 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
793 		1u,											// deUint32				queueFamilyCount;
794 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
795 	};
796 
797 	Move<VkBuffer>							buffer					= createBuffer(vk, vkDevice, &vertexBufferParams);
798 	de::MovePtr<vk::Allocation>				alloc					= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
799 	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
800 
801 	deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
802 	flushAlloc(vk, vkDevice, *alloc);
803 
804 	m_vertexBuffers.push_back(VkBufferSp(new vk::Unique<VkBuffer>(buffer)));
805 	m_vertexBufferAllocs.push_back(AllocationSp(alloc.release()));
806 }
807 
useAttribute(deUint32 bindingLocation,BaseAttributeType type)808 void ShaderRenderCaseInstance::useAttribute (deUint32 bindingLocation, BaseAttributeType type)
809 {
810 	const EnabledBaseAttribute attribute =
811 	{
812 		bindingLocation,	// deUint32				location;
813 		type				// BaseAttributeType	type;
814 	};
815 	m_enabledBaseAttributes.push_back(attribute);
816 }
817 
setupUniforms(const tcu::Vec4 & constCoords)818 void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
819 {
820 	if (m_uniformSetup)
821 		m_uniformSetup->setup(*this, constCoords);
822 }
823 
useUniform(deUint32 bindingLocation,BaseUniformType type)824 void ShaderRenderCaseInstance::useUniform (deUint32 bindingLocation, BaseUniformType type)
825 {
826 	#define UNIFORM_CASE(type, value) case type: addUniform(bindingLocation, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, value); break
827 
828 	switch(type)
829 	{
830 		// Bool
831 		UNIFORM_CASE(UB_FALSE,	0);
832 		UNIFORM_CASE(UB_TRUE,	1);
833 
834 		// BVec4
835 		UNIFORM_CASE(UB4_FALSE,	tcu::Vec4(0));
836 		UNIFORM_CASE(UB4_TRUE,	tcu::Vec4(1));
837 
838 		// Integer
839 		UNIFORM_CASE(UI_ZERO,	0);
840 		UNIFORM_CASE(UI_ONE,	1);
841 		UNIFORM_CASE(UI_TWO,	2);
842 		UNIFORM_CASE(UI_THREE,	3);
843 		UNIFORM_CASE(UI_FOUR,	4);
844 		UNIFORM_CASE(UI_FIVE,	5);
845 		UNIFORM_CASE(UI_SIX,	6);
846 		UNIFORM_CASE(UI_SEVEN,	7);
847 		UNIFORM_CASE(UI_EIGHT,	8);
848 		UNIFORM_CASE(UI_ONEHUNDREDONE, 101);
849 
850 		// IVec2
851 		UNIFORM_CASE(UI2_MINUS_ONE,	tcu::IVec2(-1));
852 		UNIFORM_CASE(UI2_ZERO,		tcu::IVec2(0));
853 		UNIFORM_CASE(UI2_ONE,		tcu::IVec2(1));
854 		UNIFORM_CASE(UI2_TWO,		tcu::IVec2(2));
855 		UNIFORM_CASE(UI2_THREE,		tcu::IVec2(3));
856 		UNIFORM_CASE(UI2_FOUR,		tcu::IVec2(4));
857 		UNIFORM_CASE(UI2_FIVE,		tcu::IVec2(5));
858 
859 		// IVec3
860 		UNIFORM_CASE(UI3_MINUS_ONE,	tcu::IVec3(-1));
861 		UNIFORM_CASE(UI3_ZERO,		tcu::IVec3(0));
862 		UNIFORM_CASE(UI3_ONE,		tcu::IVec3(1));
863 		UNIFORM_CASE(UI3_TWO,		tcu::IVec3(2));
864 		UNIFORM_CASE(UI3_THREE,		tcu::IVec3(3));
865 		UNIFORM_CASE(UI3_FOUR,		tcu::IVec3(4));
866 		UNIFORM_CASE(UI3_FIVE,		tcu::IVec3(5));
867 
868 		// IVec4
869 		UNIFORM_CASE(UI4_MINUS_ONE, tcu::IVec4(-1));
870 		UNIFORM_CASE(UI4_ZERO,		tcu::IVec4(0));
871 		UNIFORM_CASE(UI4_ONE,		tcu::IVec4(1));
872 		UNIFORM_CASE(UI4_TWO,		tcu::IVec4(2));
873 		UNIFORM_CASE(UI4_THREE,		tcu::IVec4(3));
874 		UNIFORM_CASE(UI4_FOUR,		tcu::IVec4(4));
875 		UNIFORM_CASE(UI4_FIVE,		tcu::IVec4(5));
876 
877 		// Float
878 		UNIFORM_CASE(UF_ZERO,		0.0f);
879 		UNIFORM_CASE(UF_ONE,		1.0f);
880 		UNIFORM_CASE(UF_TWO,		2.0f);
881 		UNIFORM_CASE(UF_THREE,		3.0f);
882 		UNIFORM_CASE(UF_FOUR,		4.0f);
883 		UNIFORM_CASE(UF_FIVE,		5.0f);
884 		UNIFORM_CASE(UF_SIX,		6.0f);
885 		UNIFORM_CASE(UF_SEVEN,		7.0f);
886 		UNIFORM_CASE(UF_EIGHT,		8.0f);
887 
888 		UNIFORM_CASE(UF_HALF,		1.0f / 2.0f);
889 		UNIFORM_CASE(UF_THIRD,		1.0f / 3.0f);
890 		UNIFORM_CASE(UF_FOURTH,		1.0f / 4.0f);
891 		UNIFORM_CASE(UF_FIFTH,		1.0f / 5.0f);
892 		UNIFORM_CASE(UF_SIXTH,		1.0f / 6.0f);
893 		UNIFORM_CASE(UF_SEVENTH,	1.0f / 7.0f);
894 		UNIFORM_CASE(UF_EIGHTH,		1.0f / 8.0f);
895 
896 		// Vec2
897 		UNIFORM_CASE(UV2_MINUS_ONE,	tcu::Vec2(-1.0f));
898 		UNIFORM_CASE(UV2_ZERO,		tcu::Vec2(0.0f));
899 		UNIFORM_CASE(UV2_ONE,		tcu::Vec2(1.0f));
900 		UNIFORM_CASE(UV2_TWO,		tcu::Vec2(2.0f));
901 		UNIFORM_CASE(UV2_THREE,		tcu::Vec2(3.0f));
902 
903 		UNIFORM_CASE(UV2_HALF,		tcu::Vec2(1.0f / 2.0f));
904 
905 		// Vec3
906 		UNIFORM_CASE(UV3_MINUS_ONE,	tcu::Vec3(-1.0f));
907 		UNIFORM_CASE(UV3_ZERO,		tcu::Vec3(0.0f));
908 		UNIFORM_CASE(UV3_ONE,		tcu::Vec3(1.0f));
909 		UNIFORM_CASE(UV3_TWO,		tcu::Vec3(2.0f));
910 		UNIFORM_CASE(UV3_THREE,		tcu::Vec3(3.0f));
911 
912 		UNIFORM_CASE(UV3_HALF,		tcu::Vec3(1.0f / 2.0f));
913 
914 		// Vec4
915 		UNIFORM_CASE(UV4_MINUS_ONE,	tcu::Vec4(-1.0f));
916 		UNIFORM_CASE(UV4_ZERO,		tcu::Vec4(0.0f));
917 		UNIFORM_CASE(UV4_ONE,		tcu::Vec4(1.0f));
918 		UNIFORM_CASE(UV4_TWO,		tcu::Vec4(2.0f));
919 		UNIFORM_CASE(UV4_THREE,		tcu::Vec4(3.0f));
920 
921 		UNIFORM_CASE(UV4_HALF,		tcu::Vec4(1.0f / 2.0f));
922 
923 		UNIFORM_CASE(UV4_BLACK,		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
924 		UNIFORM_CASE(UV4_GRAY,		tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
925 		UNIFORM_CASE(UV4_WHITE,		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
926 
927 		default:
928 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unknown Uniform type: " << type << tcu::TestLog::EndMessage;
929 			break;
930 	}
931 
932 	#undef UNIFORM_CASE
933 }
934 
getViewportSize(void) const935 const tcu::UVec2 ShaderRenderCaseInstance::getViewportSize (void) const
936 {
937 	return tcu::UVec2(de::min(m_renderSize.x(), MAX_RENDER_WIDTH),
938 					  de::min(m_renderSize.y(), MAX_RENDER_HEIGHT));
939 }
940 
setSampleCount(VkSampleCountFlagBits sampleCount)941 void ShaderRenderCaseInstance::setSampleCount (VkSampleCountFlagBits sampleCount)
942 {
943 	m_sampleCount	= sampleCount;
944 }
945 
isMultiSampling(void) const946 bool ShaderRenderCaseInstance::isMultiSampling (void) const
947 {
948 	return m_sampleCount != VK_SAMPLE_COUNT_1_BIT;
949 }
950 
uploadImage(const tcu::TextureFormat & texFormat,const TextureData & textureData,const tcu::Sampler & refSampler,deUint32 mipLevels,deUint32 arrayLayers,VkImage destImage)951 void ShaderRenderCaseInstance::uploadImage (const tcu::TextureFormat&			texFormat,
952 											const TextureData&					textureData,
953 											const tcu::Sampler&					refSampler,
954 											deUint32							mipLevels,
955 											deUint32							arrayLayers,
956 											VkImage								destImage)
957 {
958 	const VkDevice					vkDevice				= getDevice();
959 	const DeviceInterface&			vk						= getDeviceInterface();
960 	const VkQueue					queue					= getUniversalQueue();
961 	const deUint32					queueFamilyIndex		= getUniversalQueueFamilyIndex();
962 
963 	const bool						isShadowSampler			= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
964 	const VkImageAspectFlags		aspectMask				= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
965 	deUint32						bufferSize				= 0u;
966 	Move<VkBuffer>					buffer;
967 	de::MovePtr<Allocation>			bufferAlloc;
968 	Move<VkCommandPool>				cmdPool;
969 	Move<VkCommandBuffer>			cmdBuffer;
970 	std::vector<VkBufferImageCopy>	copyRegions;
971 	std::vector<deUint32>			offsetMultiples;
972 
973 	offsetMultiples.push_back(4u);
974 	offsetMultiples.push_back(texFormat.getPixelSize());
975 
976 	// Calculate buffer size
977 	for (TextureData::const_iterator mit = textureData.begin(); mit != textureData.end(); ++mit)
978 	{
979 		for (TextureLayerData::const_iterator lit = mit->begin(); lit != mit->end(); ++lit)
980 		{
981 			const tcu::ConstPixelBufferAccess&	access	= *lit;
982 
983 			bufferSize = getNextMultiple(offsetMultiples, bufferSize);
984 			bufferSize += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
985 		}
986 	}
987 
988 	// Create source buffer
989 	{
990 		const VkBufferCreateInfo bufferParams =
991 		{
992 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
993 			DE_NULL,									// const void*			pNext;
994 			0u,											// VkBufferCreateFlags	flags;
995 			bufferSize,									// VkDeviceSize			size;
996 			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
997 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
998 			0u,											// deUint32				queueFamilyIndexCount;
999 			DE_NULL,									// const deUint32*		pQueueFamilyIndices;
1000 		};
1001 
1002 		buffer		= createBuffer(vk, vkDevice, &bufferParams);
1003 		bufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
1004 		VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
1005 	}
1006 
1007 	// Get copy regions and write buffer data
1008 	{
1009 		deUint32	layerDataOffset		= 0;
1010 		deUint8*	destPtr				= (deUint8*)bufferAlloc->getHostPtr();
1011 
1012 		for (size_t levelNdx = 0; levelNdx < textureData.size(); levelNdx++)
1013 		{
1014 			const TextureLayerData&		layerData	= textureData[levelNdx];
1015 
1016 			for (size_t layerNdx = 0; layerNdx < layerData.size(); layerNdx++)
1017 			{
1018 				layerDataOffset = getNextMultiple(offsetMultiples, layerDataOffset);
1019 
1020 				const tcu::ConstPixelBufferAccess&	access		= layerData[layerNdx];
1021 				const tcu::PixelBufferAccess		destAccess	(access.getFormat(), access.getSize(), destPtr + layerDataOffset);
1022 
1023 				const VkBufferImageCopy				layerRegion =
1024 				{
1025 					layerDataOffset,						// VkDeviceSize				bufferOffset;
1026 					(deUint32)access.getWidth(),			// deUint32					bufferRowLength;
1027 					(deUint32)access.getHeight(),			// deUint32					bufferImageHeight;
1028 					{										// VkImageSubresourceLayers	imageSubresource;
1029 						aspectMask,								// VkImageAspectFlags		aspectMask;
1030 						(deUint32)levelNdx,						// uint32_t					mipLevel;
1031 						(deUint32)layerNdx,						// uint32_t					baseArrayLayer;
1032 						1u										// uint32_t					layerCount;
1033 					},
1034 					{ 0u, 0u, 0u },							// VkOffset3D			imageOffset;
1035 					{										// VkExtent3D			imageExtent;
1036 						(deUint32)access.getWidth(),
1037 						(deUint32)access.getHeight(),
1038 						(deUint32)access.getDepth()
1039 					}
1040 				};
1041 
1042 				copyRegions.push_back(layerRegion);
1043 				tcu::copy(destAccess, access);
1044 
1045 				layerDataOffset += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
1046 			}
1047 		}
1048 	}
1049 
1050 	flushAlloc(vk, vkDevice, *bufferAlloc);
1051 
1052 	copyBufferToImage(vk, vkDevice, queue, queueFamilyIndex, *buffer, bufferSize, copyRegions, DE_NULL, aspectMask, mipLevels, arrayLayers, destImage);
1053 }
1054 
clearImage(const tcu::Sampler & refSampler,deUint32 mipLevels,deUint32 arrayLayers,VkImage destImage)1055 void ShaderRenderCaseInstance::clearImage (const tcu::Sampler&					refSampler,
1056 										   deUint32								mipLevels,
1057 										   deUint32								arrayLayers,
1058 										   VkImage								destImage)
1059 {
1060 	const VkDevice					vkDevice				= m_context.getDevice();
1061 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
1062 	const VkQueue					queue					= m_context.getUniversalQueue();
1063 	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
1064 
1065 	const bool						isShadowSampler			= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
1066 	const VkImageAspectFlags		aspectMask				= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
1067 	Move<VkCommandPool>				cmdPool;
1068 	Move<VkCommandBuffer>			cmdBuffer;
1069 
1070 	VkClearValue					clearValue;
1071 	deMemset(&clearValue, 0, sizeof(clearValue));
1072 
1073 
1074 	// Create command pool and buffer
1075 	cmdPool		= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1076 	cmdBuffer	= allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1077 
1078 	const VkImageMemoryBarrier preImageBarrier =
1079 	{
1080 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1081 		DE_NULL,										// const void*				pNext;
1082 		0u,												// VkAccessFlags			srcAccessMask;
1083 		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
1084 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
1085 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
1086 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1087 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1088 		destImage,										// VkImage					image;
1089 		{												// VkImageSubresourceRange	subresourceRange;
1090 			aspectMask,								// VkImageAspect	aspect;
1091 			0u,										// deUint32			baseMipLevel;
1092 			mipLevels,								// deUint32			mipLevels;
1093 			0u,										// deUint32			baseArraySlice;
1094 			arrayLayers								// deUint32			arraySize;
1095 		}
1096 	};
1097 
1098 	const VkImageMemoryBarrier postImageBarrier =
1099 	{
1100 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1101 		DE_NULL,										// const void*				pNext;
1102 		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
1103 		VK_ACCESS_SHADER_READ_BIT,						// VkAccessFlags			dstAccessMask;
1104 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout;
1105 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,		// VkImageLayout			newLayout;
1106 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1107 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1108 		destImage,										// VkImage					image;
1109 		{												// VkImageSubresourceRange	subresourceRange;
1110 			aspectMask,								// VkImageAspect	aspect;
1111 			0u,										// deUint32			baseMipLevel;
1112 			mipLevels,								// deUint32			mipLevels;
1113 			0u,										// deUint32			baseArraySlice;
1114 			arrayLayers								// deUint32			arraySize;
1115 		}
1116 	};
1117 
1118 	const VkImageSubresourceRange clearRange		=
1119 	{
1120 		aspectMask,										// VkImageAspectFlags	aspectMask;
1121 		0u,												// deUint32				baseMipLevel;
1122 		mipLevels,										// deUint32				levelCount;
1123 		0u,												// deUint32				baseArrayLayer;
1124 		arrayLayers										// deUint32				layerCount;
1125 	};
1126 
1127 	// Copy buffer to image
1128 	beginCommandBuffer(vk, *cmdBuffer);
1129 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
1130 	if (aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
1131 	{
1132 		vk.cmdClearColorImage(*cmdBuffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &clearRange);
1133 	}
1134 	else
1135 	{
1136 		vk.cmdClearDepthStencilImage(*cmdBuffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.depthStencil, 1, &clearRange);
1137 	}
1138 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
1139 	endCommandBuffer(vk, *cmdBuffer);
1140 
1141 	submitCommandsAndWait(vk, vkDevice, queue, cmdBuffer.get());
1142 }
1143 
mipLevelExtents(const VkExtent3D & baseExtents,const deUint32 mipLevel)1144 VkExtent3D mipLevelExtents (const VkExtent3D& baseExtents, const deUint32 mipLevel)
1145 {
1146 	VkExtent3D result;
1147 
1148 	result.width	= std::max(baseExtents.width  >> mipLevel, 1u);
1149 	result.height	= std::max(baseExtents.height >> mipLevel, 1u);
1150 	result.depth	= std::max(baseExtents.depth  >> mipLevel, 1u);
1151 
1152 	return result;
1153 }
1154 
alignedDivide(const VkExtent3D & extent,const VkExtent3D & divisor)1155 tcu::UVec3 alignedDivide (const VkExtent3D& extent, const VkExtent3D& divisor)
1156 {
1157 	tcu::UVec3 result;
1158 
1159 	result.x() = extent.width  / divisor.width  + ((extent.width  % divisor.width != 0)  ? 1u : 0u);
1160 	result.y() = extent.height / divisor.height + ((extent.height % divisor.height != 0) ? 1u : 0u);
1161 	result.z() = extent.depth  / divisor.depth  + ((extent.depth  % divisor.depth != 0)  ? 1u : 0u);
1162 
1163 	return result;
1164 }
1165 
isImageSizeSupported(const VkImageType imageType,const tcu::UVec3 & imageSize,const vk::VkPhysicalDeviceLimits & limits)1166 bool isImageSizeSupported (const VkImageType imageType, const tcu::UVec3& imageSize, const vk::VkPhysicalDeviceLimits& limits)
1167 {
1168 	switch (imageType)
1169 	{
1170 		case VK_IMAGE_TYPE_1D:
1171 			return (imageSize.x() <= limits.maxImageDimension1D
1172 				 && imageSize.y() == 1
1173 				 && imageSize.z() == 1);
1174 		case VK_IMAGE_TYPE_2D:
1175 			return (imageSize.x() <= limits.maxImageDimension2D
1176 				 && imageSize.y() <= limits.maxImageDimension2D
1177 				 && imageSize.z() == 1);
1178 		case VK_IMAGE_TYPE_3D:
1179 			return (imageSize.x() <= limits.maxImageDimension3D
1180 				 && imageSize.y() <= limits.maxImageDimension3D
1181 				 && imageSize.z() <= limits.maxImageDimension3D);
1182 		default:
1183 			DE_FATAL("Unknown image type");
1184 			return false;
1185 	}
1186 }
1187 
checkSparseSupport(const VkImageCreateInfo & imageInfo) const1188 void ShaderRenderCaseInstance::checkSparseSupport (const VkImageCreateInfo& imageInfo) const
1189 {
1190 	const InstanceInterface&		instance		= getInstanceInterface();
1191 	const VkPhysicalDevice			physicalDevice	= getPhysicalDevice();
1192 	const VkPhysicalDeviceFeatures	deviceFeatures	= getPhysicalDeviceFeatures(instance, physicalDevice);
1193 
1194 	const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec = getPhysicalDeviceSparseImageFormatProperties(
1195 		instance, physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.samples, imageInfo.usage, imageInfo.tiling);
1196 
1197 	if (!deviceFeatures.shaderResourceResidency)
1198 		TCU_THROW(NotSupportedError, "Required feature: shaderResourceResidency.");
1199 
1200 	if (!deviceFeatures.sparseBinding)
1201 		TCU_THROW(NotSupportedError, "Required feature: sparseBinding.");
1202 
1203 	if (imageInfo.imageType == VK_IMAGE_TYPE_2D && !deviceFeatures.sparseResidencyImage2D)
1204 		TCU_THROW(NotSupportedError, "Required feature: sparseResidencyImage2D.");
1205 
1206 	if (imageInfo.imageType == VK_IMAGE_TYPE_3D && !deviceFeatures.sparseResidencyImage3D)
1207 		TCU_THROW(NotSupportedError, "Required feature: sparseResidencyImage3D.");
1208 
1209 	if (sparseImageFormatPropVec.size() == 0)
1210 		TCU_THROW(NotSupportedError, "The image format does not support sparse operations");
1211 }
1212 
uploadSparseImage(const tcu::TextureFormat & texFormat,const TextureData & textureData,const tcu::Sampler & refSampler,const deUint32 mipLevels,const deUint32 arrayLayers,const VkImage sparseImage,const VkImageCreateInfo & imageCreateInfo,const tcu::UVec3 texSize)1213 void ShaderRenderCaseInstance::uploadSparseImage (const tcu::TextureFormat&		texFormat,
1214 												  const TextureData&			textureData,
1215 												  const tcu::Sampler&			refSampler,
1216 												  const deUint32				mipLevels,
1217 												  const deUint32				arrayLayers,
1218 												  const VkImage					sparseImage,
1219 												  const VkImageCreateInfo&		imageCreateInfo,
1220 												  const tcu::UVec3				texSize)
1221 {
1222 	const VkDevice							vkDevice				= getDevice();
1223 	const DeviceInterface&					vk						= getDeviceInterface();
1224 	const VkPhysicalDevice					physicalDevice			= getPhysicalDevice();
1225 	const VkQueue							queue					= getUniversalQueue();
1226 	const VkQueue							sparseQueue				= getSparseQueue();
1227 	const deUint32							queueFamilyIndex		= getUniversalQueueFamilyIndex();
1228 	const InstanceInterface&				instance				= getInstanceInterface();
1229 	const VkPhysicalDeviceProperties		deviceProperties		= getPhysicalDeviceProperties(instance, physicalDevice);
1230 	const bool								isShadowSampler			= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
1231 	const VkImageAspectFlags				aspectMask				= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
1232 	const Unique<VkSemaphore>				imageMemoryBindSemaphore(createSemaphore(vk, vkDevice));
1233 	Move<VkBuffer>							buffer;
1234 	deUint32								bufferSize				= 0u;
1235 	de::MovePtr<Allocation>					bufferAlloc;
1236 	std::vector<VkBufferImageCopy>			copyRegions;
1237 	std::vector<deUint32>					offsetMultiples;
1238 
1239 	offsetMultiples.push_back(4u);
1240 	offsetMultiples.push_back(texFormat.getPixelSize());
1241 
1242 	if (isImageSizeSupported(imageCreateInfo.imageType, texSize, deviceProperties.limits) == false)
1243 		TCU_THROW(NotSupportedError, "Image size not supported for device.");
1244 
1245 	allocateAndBindSparseImage(vk, vkDevice, physicalDevice, instance, imageCreateInfo, *imageMemoryBindSemaphore, sparseQueue, m_memAlloc, m_allocations, texFormat, sparseImage);
1246 
1247 	// Calculate buffer size
1248 	for (TextureData::const_iterator mit = textureData.begin(); mit != textureData.end(); ++mit)
1249 	{
1250 		for (TextureLayerData::const_iterator lit = mit->begin(); lit != mit->end(); ++lit)
1251 		{
1252 			const tcu::ConstPixelBufferAccess&	access	= *lit;
1253 
1254 			bufferSize = getNextMultiple(offsetMultiples, bufferSize);
1255 			bufferSize += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
1256 		}
1257 	}
1258 
1259 	{
1260 		// Create source buffer
1261 		const VkBufferCreateInfo bufferParams =
1262 		{
1263 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1264 			DE_NULL,								// const void*			pNext;
1265 			0u,										// VkBufferCreateFlags	flags;
1266 			bufferSize,								// VkDeviceSize			size;
1267 			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,		// VkBufferUsageFlags	usage;
1268 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1269 			0u,										// deUint32				queueFamilyIndexCount;
1270 			DE_NULL,								// const deUint32*		pQueueFamilyIndices;
1271 		};
1272 
1273 		buffer		= createBuffer(vk, vkDevice, &bufferParams);
1274 		bufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
1275 
1276 		VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
1277 	}
1278 
1279 	// Get copy regions and write buffer data
1280 	{
1281 		deUint32	layerDataOffset		= 0;
1282 		deUint8*	destPtr				= (deUint8*)bufferAlloc->getHostPtr();
1283 
1284 		for (size_t levelNdx = 0; levelNdx < textureData.size(); levelNdx++)
1285 		{
1286 			const TextureLayerData&		layerData	= textureData[levelNdx];
1287 
1288 			for (size_t layerNdx = 0; layerNdx < layerData.size(); layerNdx++)
1289 			{
1290 				layerDataOffset = getNextMultiple(offsetMultiples, layerDataOffset);
1291 
1292 				const tcu::ConstPixelBufferAccess&	access		= layerData[layerNdx];
1293 				const tcu::PixelBufferAccess		destAccess	(access.getFormat(), access.getSize(), destPtr + layerDataOffset);
1294 
1295 				const VkBufferImageCopy				layerRegion =
1296 				{
1297 					layerDataOffset,						// VkDeviceSize				bufferOffset;
1298 					(deUint32)access.getWidth(),			// deUint32					bufferRowLength;
1299 					(deUint32)access.getHeight(),			// deUint32					bufferImageHeight;
1300 					{										// VkImageSubresourceLayers	imageSubresource;
1301 						aspectMask,								// VkImageAspectFlags		aspectMask;
1302 						(deUint32)levelNdx,						// uint32_t					mipLevel;
1303 						(deUint32)layerNdx,						// uint32_t					baseArrayLayer;
1304 						1u										// uint32_t					layerCount;
1305 					},
1306 					{ 0u, 0u, 0u },							// VkOffset3D			imageOffset;
1307 					{										// VkExtent3D			imageExtent;
1308 						(deUint32)access.getWidth(),
1309 						(deUint32)access.getHeight(),
1310 						(deUint32)access.getDepth()
1311 					}
1312 				};
1313 
1314 				copyRegions.push_back(layerRegion);
1315 				tcu::copy(destAccess, access);
1316 
1317 				layerDataOffset += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
1318 			}
1319 		}
1320 	}
1321 	copyBufferToImage(vk, vkDevice, queue, queueFamilyIndex, *buffer, bufferSize, copyRegions, &(*imageMemoryBindSemaphore), aspectMask, mipLevels, arrayLayers, sparseImage);
1322 }
1323 
useSampler(deUint32 bindingLocation,deUint32 textureId)1324 void ShaderRenderCaseInstance::useSampler (deUint32 bindingLocation, deUint32 textureId)
1325 {
1326 	DE_ASSERT(textureId < m_textures.size());
1327 
1328 	const TextureBinding&				textureBinding		= *m_textures[textureId];
1329 	const TextureBinding::Type			textureType			= textureBinding.getType();
1330 	const tcu::Sampler&					refSampler			= textureBinding.getSampler();
1331 	const TextureBinding::Parameters&	textureParams		= textureBinding.getParameters();
1332 	const bool							isMSTexture			= textureParams.samples != vk::VK_SAMPLE_COUNT_1_BIT;
1333 	deUint32							mipLevels			= 1u;
1334 	deUint32							arrayLayers			= 1u;
1335 	tcu::TextureFormat					texFormat;
1336 	tcu::UVec3							texSize;
1337 	TextureData							textureData;
1338 
1339 	if (textureType == TextureBinding::TYPE_2D)
1340 	{
1341 		const tcu::Texture2D&			texture		= textureBinding.get2D();
1342 
1343 		texFormat									= texture.getFormat();
1344 		texSize										= tcu::UVec3(texture.getWidth(), texture.getHeight(), 1u);
1345 		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1346 		arrayLayers									= 1u;
1347 
1348 		textureData.resize(mipLevels);
1349 
1350 		for (deUint32 level = 0; level < mipLevels; ++level)
1351 		{
1352 			if (texture.isLevelEmpty(level))
1353 				continue;
1354 
1355 			textureData[level].push_back(texture.getLevel(level));
1356 		}
1357 	}
1358 	else if (textureType == TextureBinding::TYPE_CUBE_MAP)
1359 	{
1360 		const tcu::TextureCube&			texture		= textureBinding.getCube();
1361 
1362 		texFormat									= texture.getFormat();
1363 		texSize										= tcu::UVec3(texture.getSize(), texture.getSize(), 1u);
1364 		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1365 		arrayLayers									= 6u;
1366 
1367 		static const tcu::CubeFace		cubeFaceMapping[tcu::CUBEFACE_LAST] =
1368 		{
1369 			tcu::CUBEFACE_POSITIVE_X,
1370 			tcu::CUBEFACE_NEGATIVE_X,
1371 			tcu::CUBEFACE_POSITIVE_Y,
1372 			tcu::CUBEFACE_NEGATIVE_Y,
1373 			tcu::CUBEFACE_POSITIVE_Z,
1374 			tcu::CUBEFACE_NEGATIVE_Z
1375 		};
1376 
1377 		textureData.resize(mipLevels);
1378 
1379 		for (deUint32 level = 0; level < mipLevels; ++level)
1380 		{
1381 			for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1382 			{
1383 				tcu::CubeFace face = cubeFaceMapping[faceNdx];
1384 
1385 				if (texture.isLevelEmpty(face, level))
1386 					continue;
1387 
1388 				textureData[level].push_back(texture.getLevelFace(level, face));
1389 			}
1390 		}
1391 	}
1392 	else if (textureType == TextureBinding::TYPE_2D_ARRAY)
1393 	{
1394 		const tcu::Texture2DArray&		texture		= textureBinding.get2DArray();
1395 
1396 		texFormat									= texture.getFormat();
1397 		texSize										= tcu::UVec3(texture.getWidth(), texture.getHeight(), 1u);
1398 		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1399 		arrayLayers									= (deUint32)texture.getNumLayers();
1400 
1401 		textureData.resize(mipLevels);
1402 
1403 		for (deUint32 level = 0; level < mipLevels; ++level)
1404 		{
1405 			if (texture.isLevelEmpty(level))
1406 				continue;
1407 
1408 			const tcu::ConstPixelBufferAccess&	levelLayers		= texture.getLevel(level);
1409 			const deUint32						layerSize		= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1410 
1411 			for (deUint32 layer = 0; layer < arrayLayers; ++layer)
1412 			{
1413 				const deUint32					layerOffset		= layerSize * layer;
1414 				tcu::ConstPixelBufferAccess		layerData		(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1415 				textureData[level].push_back(layerData);
1416 			}
1417 		}
1418 	}
1419 	else if (textureType == TextureBinding::TYPE_3D)
1420 	{
1421 		const tcu::Texture3D&			texture		= textureBinding.get3D();
1422 
1423 		texFormat									= texture.getFormat();
1424 		texSize										= tcu::UVec3(texture.getWidth(), texture.getHeight(), texture.getDepth());
1425 		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1426 		arrayLayers									= 1u;
1427 
1428 		textureData.resize(mipLevels);
1429 
1430 		for (deUint32 level = 0; level < mipLevels; ++level)
1431 		{
1432 			if (texture.isLevelEmpty(level))
1433 				continue;
1434 
1435 			textureData[level].push_back(texture.getLevel(level));
1436 		}
1437 	}
1438 	else if (textureType == TextureBinding::TYPE_1D)
1439 	{
1440 		const tcu::Texture1D&			texture		= textureBinding.get1D();
1441 
1442 		texFormat									= texture.getFormat();
1443 		texSize										= tcu::UVec3(texture.getWidth(), 1, 1);
1444 		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1445 		arrayLayers									= 1u;
1446 
1447 		textureData.resize(mipLevels);
1448 
1449 		for (deUint32 level = 0; level < mipLevels; ++level)
1450 		{
1451 			if (texture.isLevelEmpty(level))
1452 				continue;
1453 
1454 			textureData[level].push_back(texture.getLevel(level));
1455 		}
1456 	}
1457 	else if (textureType == TextureBinding::TYPE_1D_ARRAY)
1458 	{
1459 		const tcu::Texture1DArray&		texture		= textureBinding.get1DArray();
1460 
1461 		texFormat									= texture.getFormat();
1462 		texSize										= tcu::UVec3(texture.getWidth(), 1, 1);
1463 		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1464 		arrayLayers									= (deUint32)texture.getNumLayers();
1465 
1466 		textureData.resize(mipLevels);
1467 
1468 		for (deUint32 level = 0; level < mipLevels; ++level)
1469 		{
1470 			if (texture.isLevelEmpty(level))
1471 				continue;
1472 
1473 			const tcu::ConstPixelBufferAccess&	levelLayers		= texture.getLevel(level);
1474 			const deUint32						layerSize		= levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
1475 
1476 			for (deUint32 layer = 0; layer < arrayLayers; ++layer)
1477 			{
1478 				const deUint32					layerOffset		= layerSize * layer;
1479 				tcu::ConstPixelBufferAccess		layerData		(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1480 				textureData[level].push_back(layerData);
1481 			}
1482 		}
1483 	}
1484 	else if (textureType == TextureBinding::TYPE_CUBE_ARRAY)
1485 	{
1486 		const tcu::TextureCubeArray&	texture		= textureBinding.getCubeArray();
1487 		texFormat									= texture.getFormat();
1488 		texSize										= tcu::UVec3(texture.getSize(), texture.getSize(), 1);
1489 		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1490 		arrayLayers									= texture.getDepth();
1491 
1492 		textureData.resize(mipLevels);
1493 
1494 		for (deUint32 level = 0; level < mipLevels; ++level)
1495 		{
1496 			if (texture.isLevelEmpty(level))
1497 				continue;
1498 
1499 			const tcu::ConstPixelBufferAccess&	levelLayers		= texture.getLevel(level);
1500 			const deUint32						layerSize		= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1501 
1502 			for (deUint32 layer = 0; layer < arrayLayers; ++layer)
1503 			{
1504 				const deUint32					layerOffset		= layerSize * layer;
1505 				tcu::ConstPixelBufferAccess		layerData		(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1506 				textureData[level].push_back(layerData);
1507 			}
1508 		}
1509 	}
1510 	else
1511 	{
1512 		TCU_THROW(InternalError, "Invalid texture type");
1513 	}
1514 
1515 	createSamplerUniform(bindingLocation, textureType, textureBinding.getParameters().initialization, texFormat, texSize, textureData, refSampler, mipLevels, arrayLayers, textureParams);
1516 }
1517 
setPushConstantRanges(const deUint32 rangeCount,const vk::VkPushConstantRange * const pcRanges)1518 void ShaderRenderCaseInstance::setPushConstantRanges (const deUint32 rangeCount, const vk::VkPushConstantRange* const pcRanges)
1519 {
1520 	m_pushConstantRanges.clear();
1521 	for (deUint32 i = 0; i < rangeCount; ++i)
1522 	{
1523 		m_pushConstantRanges.push_back(pcRanges[i]);
1524 	}
1525 }
1526 
updatePushConstants(vk::VkCommandBuffer,vk::VkPipelineLayout)1527 void ShaderRenderCaseInstance::updatePushConstants (vk::VkCommandBuffer, vk::VkPipelineLayout)
1528 {
1529 }
1530 
createSamplerUniform(deUint32 bindingLocation,TextureBinding::Type textureType,TextureBinding::Init textureInit,const tcu::TextureFormat & texFormat,const tcu::UVec3 texSize,const TextureData & textureData,const tcu::Sampler & refSampler,deUint32 mipLevels,deUint32 arrayLayers,TextureBinding::Parameters textureParams)1531 void ShaderRenderCaseInstance::createSamplerUniform (deUint32						bindingLocation,
1532 													 TextureBinding::Type			textureType,
1533 													 TextureBinding::Init			textureInit,
1534 													 const tcu::TextureFormat&		texFormat,
1535 													 const tcu::UVec3				texSize,
1536 													 const TextureData&				textureData,
1537 													 const tcu::Sampler&			refSampler,
1538 													 deUint32						mipLevels,
1539 													 deUint32						arrayLayers,
1540 													 TextureBinding::Parameters		textureParams)
1541 {
1542 	const VkDevice					vkDevice			= getDevice();
1543 	const DeviceInterface&			vk					= getDeviceInterface();
1544 	const deUint32					queueFamilyIndex	= getUniversalQueueFamilyIndex();
1545 	const deUint32					sparseFamilyIndex	= (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE) ? getSparseQueueFamilyIndex() : queueFamilyIndex;
1546 
1547 	const bool						isShadowSampler		= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
1548 	const VkImageAspectFlags		aspectMask			= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
1549 	const VkImageViewType			imageViewType		= textureTypeToImageViewType(textureType);
1550 	const VkImageType				imageType			= viewTypeToImageType(imageViewType);
1551 	const VkSharingMode				sharingMode			= (queueFamilyIndex != sparseFamilyIndex) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
1552 	const VkFormat					format				= mapTextureFormat(texFormat);
1553 	const bool						isCube				= imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
1554 
1555 	const deUint32					queueIndexCount		= (queueFamilyIndex != sparseFamilyIndex) ? 2 : 1;
1556 	const deUint32					queueIndices[]		=
1557 	{
1558 		queueFamilyIndex,
1559 		sparseFamilyIndex
1560 	};
1561 
1562 	VkImageCreateFlags				imageCreateFlags	= isCube ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlags)0;
1563 	VkImageUsageFlags				imageUsageFlags		= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1564 	Move<VkImage>					vkTexture;
1565 	de::MovePtr<Allocation>			allocation;
1566 
1567 	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
1568 	{
1569 		imageCreateFlags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
1570 	}
1571 
1572 	// Create image
1573 	const VkImageCreateInfo			imageParams =
1574 	{
1575 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
1576 		DE_NULL,														// const void*				pNext;
1577 		imageCreateFlags,												// VkImageCreateFlags		flags;
1578 		imageType,														// VkImageType				imageType;
1579 		format,															// VkFormat					format;
1580 		{																// VkExtent3D				extent;
1581 			texSize.x(),
1582 			texSize.y(),
1583 			texSize.z()
1584 		},
1585 		mipLevels,														// deUint32					mipLevels;
1586 		arrayLayers,													// deUint32					arrayLayers;
1587 		textureParams.samples,											// VkSampleCountFlagBits	samples;
1588 		VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
1589 		imageUsageFlags,												// VkImageUsageFlags		usage;
1590 		sharingMode,													// VkSharingMode			sharingMode;
1591 		queueIndexCount,												// deUint32					queueFamilyIndexCount;
1592 		queueIndices,													// const deUint32*			pQueueFamilyIndices;
1593 		VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout;
1594 	};
1595 
1596 	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
1597 	{
1598 		checkSparseSupport(imageParams);
1599 	}
1600 
1601 	vkTexture		= createImage(vk, vkDevice, &imageParams);
1602 	allocation		= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
1603 
1604 	if (m_imageBackingMode != IMAGE_BACKING_MODE_SPARSE)
1605 	{
1606 		VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
1607 	}
1608 
1609 	switch (textureInit)
1610 	{
1611 		case TextureBinding::INIT_UPLOAD_DATA:
1612 		{
1613 			// upload*Image functions use cmdCopyBufferToImage, which is invalid for multisample images
1614 			DE_ASSERT(textureParams.samples == VK_SAMPLE_COUNT_1_BIT);
1615 
1616 			if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
1617 			{
1618 				uploadSparseImage(texFormat, textureData, refSampler, mipLevels, arrayLayers, *vkTexture, imageParams, texSize);
1619 			}
1620 			else
1621 			{
1622 				// Upload texture data
1623 				uploadImage(texFormat, textureData, refSampler, mipLevels, arrayLayers, *vkTexture);
1624 			}
1625 			break;
1626 		}
1627 		case TextureBinding::INIT_CLEAR:
1628 			clearImage(refSampler, mipLevels, arrayLayers, *vkTexture);
1629 			break;
1630 		default:
1631 			DE_FATAL("Impossible");
1632 	}
1633 
1634 	// Create sampler
1635 	const VkSamplerCreateInfo		samplerParams	= mapSampler(refSampler, texFormat);
1636 	Move<VkSampler>					sampler			= createSampler(vk, vkDevice, &samplerParams);
1637 	const deUint32					baseMipLevel	= textureParams.baseMipLevel;
1638 	const vk::VkComponentMapping	components		= textureParams.componentMapping;
1639 	const VkImageViewCreateInfo		viewParams		=
1640 	{
1641 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1642 		NULL,										// const voide*				pNext;
1643 		0u,											// VkImageViewCreateFlags	flags;
1644 		*vkTexture,									// VkImage					image;
1645 		imageViewType,								// VkImageViewType			viewType;
1646 		format,										// VkFormat					format;
1647 		components,									// VkChannelMapping			channels;
1648 		{
1649 			aspectMask,						// VkImageAspectFlags	aspectMask;
1650 			baseMipLevel,					// deUint32				baseMipLevel;
1651 			mipLevels - baseMipLevel,		// deUint32				mipLevels;
1652 			0,								// deUint32				baseArraySlice;
1653 			arrayLayers						// deUint32				arraySize;
1654 		},											// VkImageSubresourceRange	subresourceRange;
1655 	};
1656 
1657 	Move<VkImageView>				imageView		= createImageView(vk, vkDevice, &viewParams);
1658 
1659 	const vk::VkDescriptorImageInfo	descriptor		=
1660 	{
1661 		sampler.get(),								// VkSampler				sampler;
1662 		imageView.get(),							// VkImageView				imageView;
1663 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	// VkImageLayout			imageLayout;
1664 	};
1665 
1666 	de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
1667 	uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1668 	uniform->descriptor = descriptor;
1669 	uniform->location = bindingLocation;
1670 	uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
1671 	uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
1672 	uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
1673 	uniform->alloc = AllocationSp(allocation.release());
1674 
1675 	m_descriptorSetLayoutBuilder->addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_ALL, DE_NULL);
1676 	m_descriptorPoolBuilder->addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1677 
1678 	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
1679 }
1680 
setupDefaultInputs(void)1681 void ShaderRenderCaseInstance::setupDefaultInputs (void)
1682 {
1683 	/* Configuration of the vertex input attributes:
1684 		a_position   is at location 0
1685 		a_coords     is at location 1
1686 		a_unitCoords is at location 2
1687 		a_one        is at location 3
1688 
1689 	  User attributes starts from at the location 4.
1690 	*/
1691 
1692 	DE_ASSERT(m_quadGrid);
1693 	const QuadGrid&		quadGrid	= *m_quadGrid;
1694 
1695 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
1696 	addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
1697 	addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
1698 	addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
1699 
1700 	static const struct
1701 	{
1702 		BaseAttributeType	type;
1703 		int					userNdx;
1704 	} userAttributes[] =
1705 	{
1706 		{ A_IN0, 0 },
1707 		{ A_IN1, 1 },
1708 		{ A_IN2, 2 },
1709 		{ A_IN3, 3 }
1710 	};
1711 
1712 	static const struct
1713 	{
1714 		BaseAttributeType	matrixType;
1715 		int					numCols;
1716 		int					numRows;
1717 	} matrices[] =
1718 	{
1719 		{ MAT2,		2, 2 },
1720 		{ MAT2x3,	2, 3 },
1721 		{ MAT2x4,	2, 4 },
1722 		{ MAT3x2,	3, 2 },
1723 		{ MAT3,		3, 3 },
1724 		{ MAT3x4,	3, 4 },
1725 		{ MAT4x2,	4, 2 },
1726 		{ MAT4x3,	4, 3 },
1727 		{ MAT4,		4, 4 }
1728 	};
1729 
1730 	for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
1731 	{
1732 		for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
1733 		{
1734 			if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
1735 				continue;
1736 
1737 			addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
1738 		}
1739 
1740 		for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
1741 		{
1742 
1743 			if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
1744 				continue;
1745 
1746 			const int numCols = matrices[matNdx].numCols;
1747 
1748 			for (int colNdx = 0; colNdx < numCols; colNdx++)
1749 			{
1750 				addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(4 * sizeof(float)), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
1751 			}
1752 		}
1753 	}
1754 }
1755 
render(deUint32 numVertices,deUint32 numTriangles,const deUint16 * indices,const tcu::Vec4 & constCoords)1756 void ShaderRenderCaseInstance::render (deUint32				numVertices,
1757 									   deUint32				numTriangles,
1758 									   const deUint16*		indices,
1759 									   const tcu::Vec4&		constCoords)
1760 {
1761 	render(numVertices, numTriangles * 3, indices, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, constCoords);
1762 }
1763 
render(deUint32 numVertices,deUint32 numIndices,const deUint16 * indices,VkPrimitiveTopology topology,const tcu::Vec4 & constCoords)1764 void ShaderRenderCaseInstance::render (deUint32				numVertices,
1765 									   deUint32				numIndices,
1766 									   const deUint16*		indices,
1767 									   VkPrimitiveTopology	topology,
1768 									   const tcu::Vec4&		constCoords)
1769 {
1770 	const VkDevice										vkDevice					= getDevice();
1771 	const DeviceInterface&								vk							= getDeviceInterface();
1772 	const VkQueue										queue						= getUniversalQueue();
1773 	const deUint32										queueFamilyIndex			= getUniversalQueueFamilyIndex();
1774 
1775 	vk::Move<vk::VkImage>								colorImage;
1776 	de::MovePtr<vk::Allocation>							colorImageAlloc;
1777 	vk::Move<vk::VkImageView>							colorImageView;
1778 	vk::Move<vk::VkImage>								resolvedImage;
1779 	de::MovePtr<vk::Allocation>							resolvedImageAlloc;
1780 	vk::Move<vk::VkImageView>							resolvedImageView;
1781 	vk::Move<vk::VkRenderPass>							renderPass;
1782 	vk::Move<vk::VkFramebuffer>							framebuffer;
1783 	vk::Move<vk::VkPipelineLayout>						pipelineLayout;
1784 	vk::Move<vk::VkPipeline>							graphicsPipeline;
1785 	vk::Move<vk::VkShaderModule>						vertexShaderModule;
1786 	vk::Move<vk::VkShaderModule>						fragmentShaderModule;
1787 	vk::Move<vk::VkBuffer>								indexBuffer;
1788 	de::MovePtr<vk::Allocation>							indexBufferAlloc;
1789 	vk::Move<vk::VkDescriptorSetLayout>					descriptorSetLayout;
1790 	vk::Move<vk::VkDescriptorPool>						descriptorPool;
1791 	vk::Move<vk::VkDescriptorSet>						descriptorSet;
1792 	vk::Move<vk::VkCommandPool>							cmdPool;
1793 	vk::Move<vk::VkCommandBuffer>						cmdBuffer;
1794 
1795 	// Create color image
1796 	{
1797 		const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1798 		VkImageFormatProperties	properties;
1799 
1800 		if ((getInstanceInterface().getPhysicalDeviceImageFormatProperties(getPhysicalDevice(),
1801 																		   m_colorFormat,
1802 																		   VK_IMAGE_TYPE_2D,
1803 																		   VK_IMAGE_TILING_OPTIMAL,
1804 																		   imageUsage,
1805 																		   0u,
1806 																		   &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
1807 		{
1808 			TCU_THROW(NotSupportedError, "Format not supported");
1809 		}
1810 
1811 		if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
1812 		{
1813 			TCU_THROW(NotSupportedError, "Format not supported");
1814 		}
1815 
1816 		const VkImageCreateInfo							colorImageParams			=
1817 		{
1818 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType		sType;
1819 			DE_NULL,																	// const void*			pNext;
1820 			0u,																			// VkImageCreateFlags	flags;
1821 			VK_IMAGE_TYPE_2D,															// VkImageType			imageType;
1822 			m_colorFormat,																// VkFormat				format;
1823 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D			extent;
1824 			1u,																			// deUint32				mipLevels;
1825 			1u,																			// deUint32				arraySize;
1826 			m_sampleCount,																// deUint32				samples;
1827 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling		tiling;
1828 			imageUsage,																	// VkImageUsageFlags	usage;
1829 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode;
1830 			1u,																			// deUint32				queueFamilyCount;
1831 			&queueFamilyIndex,															// const deUint32*		pQueueFamilyIndices;
1832 			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout		initialLayout;
1833 		};
1834 
1835 		colorImage = createImage(vk, vkDevice, &colorImageParams);
1836 
1837 		// Allocate and bind color image memory
1838 		colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *colorImage), MemoryRequirement::Any);
1839 		VK_CHECK(vk.bindImageMemory(vkDevice, *colorImage, colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
1840 	}
1841 
1842 	// Create color attachment view
1843 	{
1844 		const VkImageViewCreateInfo						colorImageViewParams		=
1845 		{
1846 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1847 			DE_NULL,											// const void*				pNext;
1848 			0u,													// VkImageViewCreateFlags	flags;
1849 			*colorImage,										// VkImage					image;
1850 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1851 			m_colorFormat,										// VkFormat					format;
1852 			{
1853 				VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
1854 				VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
1855 				VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
1856 				VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
1857 			},													// VkChannelMapping			channels;
1858 			{
1859 				VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
1860 				0,								// deUint32				baseMipLevel;
1861 				1,								// deUint32				mipLevels;
1862 				0,								// deUint32				baseArraySlice;
1863 				1								// deUint32				arraySize;
1864 			},													// VkImageSubresourceRange	subresourceRange;
1865 		};
1866 
1867 		colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
1868 	}
1869 
1870 	if (isMultiSampling())
1871 	{
1872 		// Resolved Image
1873 		{
1874 			const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1875 			VkImageFormatProperties	properties;
1876 
1877 			if ((getInstanceInterface().getPhysicalDeviceImageFormatProperties(getPhysicalDevice(),
1878 																			   m_colorFormat,
1879 																			   VK_IMAGE_TYPE_2D,
1880 																			   VK_IMAGE_TILING_OPTIMAL,
1881 																			   imageUsage,
1882 																			   0,
1883 																			   &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
1884 			{
1885 				TCU_THROW(NotSupportedError, "Format not supported");
1886 			}
1887 
1888 			const VkImageCreateInfo					imageCreateInfo			=
1889 			{
1890 				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
1891 				DE_NULL,									// const void*				pNext;
1892 				0u,											// VkImageCreateFlags		flags;
1893 				VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
1894 				m_colorFormat,								// VkFormat					format;
1895 				{ m_renderSize.x(),	m_renderSize.y(), 1u },	// VkExtent3D				extent;
1896 				1u,											// deUint32					mipLevels;
1897 				1u,											// deUint32					arrayLayers;
1898 				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
1899 				VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
1900 				imageUsage,									// VkImageUsageFlags		usage;
1901 				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
1902 				1u,											// deUint32					queueFamilyIndexCount;
1903 				&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
1904 				VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
1905 			};
1906 
1907 			resolvedImage		= vk::createImage(vk, vkDevice, &imageCreateInfo, DE_NULL);
1908 			resolvedImageAlloc	= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *resolvedImage), MemoryRequirement::Any);
1909 			VK_CHECK(vk.bindImageMemory(vkDevice, *resolvedImage, resolvedImageAlloc->getMemory(), resolvedImageAlloc->getOffset()));
1910 		}
1911 
1912 		// Resolved Image View
1913 		{
1914 			const VkImageViewCreateInfo				imageViewCreateInfo		=
1915 			{
1916 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
1917 				DE_NULL,									// const void*					pNext;
1918 				0u,											// VkImageViewCreateFlags		flags;
1919 				*resolvedImage,								// VkImage						image;
1920 				VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
1921 				m_colorFormat,								// VkFormat						format;
1922 				{
1923 					VK_COMPONENT_SWIZZLE_R,					// VkChannelSwizzle		r;
1924 					VK_COMPONENT_SWIZZLE_G,					// VkChannelSwizzle		g;
1925 					VK_COMPONENT_SWIZZLE_B,					// VkChannelSwizzle		b;
1926 					VK_COMPONENT_SWIZZLE_A					// VkChannelSwizzle		a;
1927 				},
1928 				{
1929 					VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
1930 					0u,											// deUint32						baseMipLevel;
1931 					1u,											// deUint32						mipLevels;
1932 					0u,											// deUint32						baseArrayLayer;
1933 					1u,											// deUint32						arraySize;
1934 				},											// VkImageSubresourceRange		subresourceRange;
1935 			};
1936 
1937 			resolvedImageView = vk::createImageView(vk, vkDevice, &imageViewCreateInfo, DE_NULL);
1938 		}
1939 	}
1940 
1941 	// Create render pass
1942 	{
1943 		const VkAttachmentDescription					attachmentDescription[]		=
1944 		{
1945 			{
1946 				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
1947 				m_colorFormat,										// VkFormat							format;
1948 				m_sampleCount,										// deUint32							samples;
1949 				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
1950 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1951 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1952 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1953 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1954 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
1955 			},
1956 			{
1957 				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
1958 				m_colorFormat,										// VkFormat							format;
1959 				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
1960 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				loadOp;
1961 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1962 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1963 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1964 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1965 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
1966 			}
1967 		};
1968 
1969 		const VkAttachmentReference						attachmentReference			=
1970 		{
1971 			0u,													// deUint32			attachment;
1972 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1973 		};
1974 
1975 		const VkAttachmentReference						resolveAttachmentRef		=
1976 		{
1977 			1u,													// deUint32			attachment;
1978 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1979 		};
1980 
1981 		const VkSubpassDescription						subpassDescription			=
1982 		{
1983 			0u,													// VkSubpassDescriptionFlags	flags;
1984 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
1985 			0u,													// deUint32						inputCount;
1986 			DE_NULL,											// constVkAttachmentReference*	pInputAttachments;
1987 			1u,													// deUint32						colorCount;
1988 			&attachmentReference,								// constVkAttachmentReference*	pColorAttachments;
1989 			isMultiSampling() ? &resolveAttachmentRef : DE_NULL,// constVkAttachmentReference*	pResolveAttachments;
1990 			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
1991 			0u,													// deUint32						preserveCount;
1992 			DE_NULL												// constVkAttachmentReference*	pPreserveAttachments;
1993 		};
1994 
1995 		const VkRenderPassCreateInfo					renderPassParams			=
1996 		{
1997 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
1998 			DE_NULL,											// const void*						pNext;
1999 			0u,													// VkRenderPassCreateFlags			flags;
2000 			isMultiSampling() ? 2u : 1u,						// deUint32							attachmentCount;
2001 			attachmentDescription,								// const VkAttachmentDescription*	pAttachments;
2002 			1u,													// deUint32							subpassCount;
2003 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
2004 			0u,													// deUint32							dependencyCount;
2005 			DE_NULL												// const VkSubpassDependency*		pDependencies;
2006 		};
2007 
2008 		renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
2009 	}
2010 
2011 	// Create framebuffer
2012 	{
2013 		const VkImageView								attachments[]				=
2014 		{
2015 			*colorImageView,
2016 			*resolvedImageView
2017 		};
2018 
2019 		const VkFramebufferCreateInfo					framebufferParams			=
2020 		{
2021 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
2022 			DE_NULL,											// const void*					pNext;
2023 			(VkFramebufferCreateFlags)0,
2024 			*renderPass,										// VkRenderPass					renderPass;
2025 			isMultiSampling() ? 2u : 1u,						// deUint32						attachmentCount;
2026 			attachments,										// const VkImageView*			pAttachments;
2027 			(deUint32)m_renderSize.x(),							// deUint32						width;
2028 			(deUint32)m_renderSize.y(),							// deUint32						height;
2029 			1u													// deUint32						layers;
2030 		};
2031 
2032 		framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
2033 	}
2034 
2035 	// Create descriptors
2036 	{
2037 		setupUniforms(constCoords);
2038 
2039 		descriptorSetLayout = m_descriptorSetLayoutBuilder->build(vk, vkDevice);
2040 		if (!m_uniformInfos.empty())
2041 		{
2042 			descriptorPool									= m_descriptorPoolBuilder->build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2043 			const VkDescriptorSetAllocateInfo	allocInfo	=
2044 			{
2045 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
2046 				DE_NULL,
2047 				*descriptorPool,
2048 				1u,
2049 				&descriptorSetLayout.get(),
2050 			};
2051 
2052 			descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
2053 		}
2054 
2055 		for (deUint32 i = 0; i < m_uniformInfos.size(); i++)
2056 		{
2057 			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
2058 			deUint32 location = uniformInfo->location;
2059 
2060 			if (uniformInfo->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
2061 			{
2062 				const BufferUniform*	bufferInfo	= dynamic_cast<const BufferUniform*>(uniformInfo);
2063 
2064 				m_descriptorSetUpdateBuilder->writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &bufferInfo->descriptor);
2065 			}
2066 			else if (uniformInfo->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2067 			{
2068 				const SamplerUniform*	samplerInfo	= dynamic_cast<const SamplerUniform*>(uniformInfo);
2069 
2070 				m_descriptorSetUpdateBuilder->writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &samplerInfo->descriptor);
2071 			}
2072 			else
2073 				DE_FATAL("Impossible");
2074 		}
2075 
2076 		m_descriptorSetUpdateBuilder->update(vk, vkDevice);
2077 	}
2078 
2079 	// Create pipeline layout
2080 	{
2081 		const VkPushConstantRange* const				pcRanges					= m_pushConstantRanges.empty() ? DE_NULL : &m_pushConstantRanges[0];
2082 		const VkPipelineLayoutCreateInfo				pipelineLayoutParams		=
2083 		{
2084 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
2085 			DE_NULL,											// const void*					pNext;
2086 			(VkPipelineLayoutCreateFlags)0,
2087 			1u,													// deUint32						descriptorSetCount;
2088 			&*descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
2089 			deUint32(m_pushConstantRanges.size()),				// deUint32						pushConstantRangeCount;
2090 			pcRanges											// const VkPushConstantRange*	pPushConstantRanges;
2091 		};
2092 
2093 		pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
2094 	}
2095 
2096 	// Create shaders
2097 	{
2098 		vertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get(m_vertexShaderName), 0);
2099 		fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get(m_fragmentShaderName), 0);
2100 	}
2101 
2102 	// Create pipeline
2103 	{
2104 		// Add test case specific attributes
2105 		if (m_attribFunc)
2106 			m_attribFunc(*this, numVertices);
2107 
2108 		// Add base attributes
2109 		setupDefaultInputs();
2110 
2111 		const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams		=
2112 		{
2113 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
2114 			DE_NULL,														// const void*								pNext;
2115 			(VkPipelineVertexInputStateCreateFlags)0,
2116 			(deUint32)m_vertexBindingDescription.size(),					// deUint32									bindingCount;
2117 			&m_vertexBindingDescription[0],									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
2118 			(deUint32)m_vertexAttributeDescription.size(),					// deUint32									attributeCount;
2119 			&m_vertexAttributeDescription[0],								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
2120 		};
2121 
2122 		const std::vector<VkViewport>					viewports					(1, makeViewport(m_renderSize));
2123 		const std::vector<VkRect2D>						scissors					(1, makeRect2D(m_renderSize));
2124 
2125 		const VkPipelineMultisampleStateCreateInfo		multisampleStateParams =
2126 		{
2127 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
2128 			DE_NULL,														// const void*								pNext;
2129 			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
2130 			m_sampleCount,													// VkSampleCountFlagBits					rasterizationSamples;
2131 			VK_FALSE,														// VkBool32									sampleShadingEnable;
2132 			0.0f,															// float									minSampleShading;
2133 			DE_NULL,														// const VkSampleMask*						pSampleMask;
2134 			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
2135 			VK_FALSE														// VkBool32									alphaToOneEnable;
2136 		};
2137 
2138 		graphicsPipeline = makeGraphicsPipeline(vk,							// const DeviceInterface&                        vk
2139 												vkDevice,					// const VkDevice                                device
2140 												*pipelineLayout,			// const VkPipelineLayout                        pipelineLayout
2141 												*vertexShaderModule,		// const VkShaderModule                          vertexShaderModule
2142 												DE_NULL,					// const VkShaderModule                          tessellationControlShaderModule
2143 												DE_NULL,					// const VkShaderModule                          tessellationEvalShaderModule
2144 												DE_NULL,					// const VkShaderModule                          geometryShaderModule
2145 												*fragmentShaderModule,		// const VkShaderModule                          fragmentShaderModule
2146 												*renderPass,				// const VkRenderPass                            renderPass
2147 												viewports,					// const std::vector<VkViewport>&                viewports
2148 												scissors,					// const std::vector<VkRect2D>&                  scissors
2149 												topology,					// const VkPrimitiveTopology                     topology
2150 												0u,							// const deUint32                                subpass
2151 												0u,							// const deUint32                                patchControlPoints
2152 												&vertexInputStateParams,	// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
2153 												DE_NULL,					// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
2154 												&multisampleStateParams);	// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
2155 	}
2156 
2157 	// Create vertex indices buffer
2158 	if (numIndices != 0)
2159 	{
2160 		const VkDeviceSize								indexBufferSize			= numIndices * sizeof(deUint16);
2161 		const VkBufferCreateInfo						indexBufferParams		=
2162 		{
2163 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
2164 			DE_NULL,									// const void*			pNext;
2165 			0u,											// VkBufferCreateFlags	flags;
2166 			indexBufferSize,							// VkDeviceSize			size;
2167 			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
2168 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
2169 			1u,											// deUint32				queueFamilyCount;
2170 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
2171 		};
2172 
2173 		indexBuffer			= createBuffer(vk, vkDevice, &indexBufferParams);
2174 		indexBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), MemoryRequirement::HostVisible);
2175 
2176 		VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexBufferAlloc->getMemory(), indexBufferAlloc->getOffset()));
2177 
2178 		// Load vertice indices into buffer
2179 		deMemcpy(indexBufferAlloc->getHostPtr(), indices, (size_t)indexBufferSize);
2180 		flushAlloc(vk, vkDevice, *indexBufferAlloc);
2181 	}
2182 
2183 	// Create command pool
2184 	cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2185 
2186 	// Create command buffer
2187 	{
2188 		cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2189 
2190 		beginCommandBuffer(vk, *cmdBuffer);
2191 
2192 		{
2193 			const VkImageMemoryBarrier					imageBarrier				=
2194 			{
2195 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,										// VkStructureType			sType;
2196 				DE_NULL,																	// const void*				pNext;
2197 				0u,																			// VkAccessFlags			srcAccessMask;
2198 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,										// VkAccessFlags			dstAccessMask;
2199 				VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			oldLayout;
2200 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,									// VkImageLayout			newLayout;
2201 				VK_QUEUE_FAMILY_IGNORED,													// deUint32					srcQueueFamilyIndex;
2202 				VK_QUEUE_FAMILY_IGNORED,													// deUint32					dstQueueFamilyIndex;
2203 				*colorImage,																// VkImage					image;
2204 				{																			// VkImageSubresourceRange	subresourceRange;
2205 					VK_IMAGE_ASPECT_COLOR_BIT,												// VkImageAspectFlags		aspectMask;
2206 					0u,																		// deUint32					baseMipLevel;
2207 					1u,																		// deUint32					mipLevels;
2208 					0u,																		// deUint32					baseArrayLayer;
2209 					1u,																		// deUint32					arraySize;
2210 				}
2211 			};
2212 
2213 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, DE_NULL, 1, &imageBarrier);
2214 
2215 			if (isMultiSampling()) {
2216 				// add multisample barrier
2217 				const VkImageMemoryBarrier				multiSampleImageBarrier		=
2218 				{
2219 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,										// VkStructureType			sType;
2220 					DE_NULL,																	// const void*				pNext;
2221 					0u,																			// VkAccessFlags			srcAccessMask;
2222 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,										// VkAccessFlags			dstAccessMask;
2223 					VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			oldLayout;
2224 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,									// VkImageLayout			newLayout;
2225 					VK_QUEUE_FAMILY_IGNORED,													// deUint32					srcQueueFamilyIndex;
2226 					VK_QUEUE_FAMILY_IGNORED,													// deUint32					dstQueueFamilyIndex;
2227 					*resolvedImage,																// VkImage					image;
2228 					{																			// VkImageSubresourceRange	subresourceRange;
2229 						VK_IMAGE_ASPECT_COLOR_BIT,												// VkImageAspectFlags		aspectMask;
2230 						0u,																		// deUint32					baseMipLevel;
2231 						1u,																		// deUint32					mipLevels;
2232 						0u,																		// deUint32					baseArrayLayer;
2233 						1u,																		// deUint32					arraySize;
2234 					}
2235 				};
2236 
2237 				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, DE_NULL, 1, &multiSampleImageBarrier);
2238 			}
2239 		}
2240 
2241 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), m_clearColor);
2242 
2243 		updatePushConstants(*cmdBuffer, *pipelineLayout);
2244 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
2245 		if (!m_uniformInfos.empty())
2246 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1, &*descriptorSet, 0u, DE_NULL);
2247 
2248 		const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
2249 		const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
2250 
2251 		std::vector<VkBuffer> buffers(numberOfVertexAttributes);
2252 		for (size_t i = 0; i < numberOfVertexAttributes; i++)
2253 		{
2254 			buffers[i] = m_vertexBuffers[i].get()->get();
2255 		}
2256 
2257 		vk.cmdBindVertexBuffers(*cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
2258 		if (numIndices != 0)
2259 		{
2260 			vk.cmdBindIndexBuffer(*cmdBuffer, *indexBuffer, 0, VK_INDEX_TYPE_UINT16);
2261 			vk.cmdDrawIndexed(*cmdBuffer, numIndices, 1, 0, 0, 0);
2262 		}
2263 		else
2264 			vk.cmdDraw(*cmdBuffer, numVertices,  1, 0, 1);
2265 
2266 		endRenderPass(vk, *cmdBuffer);
2267 		endCommandBuffer(vk, *cmdBuffer);
2268 	}
2269 
2270 	// Execute Draw
2271 	submitCommandsAndWait(vk, vkDevice, queue, cmdBuffer.get());
2272 
2273 	// Read back the result
2274 	{
2275 		const tcu::TextureFormat						resultFormat				= mapVkFormat(m_colorFormat);
2276 		const VkDeviceSize								imageSizeBytes				= (VkDeviceSize)(resultFormat.getPixelSize() * m_renderSize.x() * m_renderSize.y());
2277 		const VkBufferCreateInfo						readImageBufferParams		=
2278 		{
2279 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//  VkStructureType		sType;
2280 			DE_NULL,									//  const void*			pNext;
2281 			0u,											//  VkBufferCreateFlags	flags;
2282 			imageSizeBytes,								//  VkDeviceSize		size;
2283 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//  VkBufferUsageFlags	usage;
2284 			VK_SHARING_MODE_EXCLUSIVE,					//  VkSharingMode		sharingMode;
2285 			1u,											//  deUint32			queueFamilyCount;
2286 			&queueFamilyIndex,							//  const deUint32*		pQueueFamilyIndices;
2287 		};
2288 		const Unique<VkBuffer>							readImageBuffer				(createBuffer(vk, vkDevice, &readImageBufferParams));
2289 		const de::UniquePtr<Allocation>					readImageBufferMemory		(m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
2290 
2291 		VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
2292 
2293 		// Copy image to buffer
2294 		const Move<VkCommandBuffer>						resultCmdBuffer				= allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2295 
2296 		beginCommandBuffer(vk, *resultCmdBuffer);
2297 
2298 		copyImageToBuffer(vk, *resultCmdBuffer, isMultiSampling() ? *resolvedImage : *colorImage, *readImageBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()));
2299 
2300 		endCommandBuffer(vk, *resultCmdBuffer);
2301 
2302 		submitCommandsAndWait(vk, vkDevice, queue, resultCmdBuffer.get());
2303 
2304 		invalidateAlloc(vk, vkDevice, *readImageBufferMemory);
2305 
2306 		const tcu::ConstPixelBufferAccess				resultAccess				(resultFormat, m_renderSize.x(), m_renderSize.y(), 1, readImageBufferMemory->getHostPtr());
2307 
2308 		m_resultImage.setStorage(resultFormat, m_renderSize.x(), m_renderSize.y());
2309 		tcu::copy(m_resultImage.getAccess(), resultAccess);
2310 	}
2311 }
2312 
computeVertexReference(tcu::Surface & result,const QuadGrid & quadGrid)2313 void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
2314 {
2315 	DE_ASSERT(m_evaluator);
2316 
2317 	// Buffer info.
2318 	const int				width		= result.getWidth();
2319 	const int				height		= result.getHeight();
2320 	const int				gridSize	= quadGrid.getGridSize();
2321 	const int				stride		= gridSize + 1;
2322 	const bool				hasAlpha	= true; // \todo [2015-09-07 elecro] add correct alpha check
2323 	ShaderEvalContext		evalCtx		(quadGrid);
2324 
2325 	// Evaluate color for each vertex.
2326 	std::vector<tcu::Vec4>	colors		((gridSize + 1) * (gridSize + 1));
2327 	for (int y = 0; y < gridSize+1; y++)
2328 	for (int x = 0; x < gridSize+1; x++)
2329 	{
2330 		const float	sx			= (float)x / (float)gridSize;
2331 		const float	sy			= (float)y / (float)gridSize;
2332 		const int	vtxNdx		= ((y * (gridSize+1)) + x);
2333 
2334 		evalCtx.reset(sx, sy);
2335 		m_evaluator->evaluate(evalCtx);
2336 		DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
2337 		tcu::Vec4 color = evalCtx.color;
2338 
2339 		if (!hasAlpha)
2340 			color.w() = 1.0f;
2341 
2342 		colors[vtxNdx] = color;
2343 	}
2344 
2345 	// Render quads.
2346 	for (int y = 0; y < gridSize; y++)
2347 	for (int x = 0; x < gridSize; x++)
2348 	{
2349 		const float		x0		= (float)x       / (float)gridSize;
2350 		const float		x1		= (float)(x + 1) / (float)gridSize;
2351 		const float		y0		= (float)y       / (float)gridSize;
2352 		const float		y1		= (float)(y + 1) / (float)gridSize;
2353 
2354 		const float		sx0		= x0 * (float)width;
2355 		const float		sx1		= x1 * (float)width;
2356 		const float		sy0		= y0 * (float)height;
2357 		const float		sy1		= y1 * (float)height;
2358 		const float		oosx	= 1.0f / (sx1 - sx0);
2359 		const float		oosy	= 1.0f / (sy1 - sy0);
2360 
2361 		const int		ix0		= deCeilFloatToInt32(sx0 - 0.5f);
2362 		const int		ix1		= deCeilFloatToInt32(sx1 - 0.5f);
2363 		const int		iy0		= deCeilFloatToInt32(sy0 - 0.5f);
2364 		const int		iy1		= deCeilFloatToInt32(sy1 - 0.5f);
2365 
2366 		const int		v00		= (y * stride) + x;
2367 		const int		v01		= (y * stride) + x + 1;
2368 		const int		v10		= ((y + 1) * stride) + x;
2369 		const int		v11		= ((y + 1) * stride) + x + 1;
2370 		const tcu::Vec4	c00		= colors[v00];
2371 		const tcu::Vec4	c01		= colors[v01];
2372 		const tcu::Vec4	c10		= colors[v10];
2373 		const tcu::Vec4	c11		= colors[v11];
2374 
2375 		//printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
2376 
2377 		for (int iy = iy0; iy < iy1; iy++)
2378 		for (int ix = ix0; ix < ix1; ix++)
2379 		{
2380 			DE_ASSERT(deInBounds32(ix, 0, width));
2381 			DE_ASSERT(deInBounds32(iy, 0, height));
2382 
2383 			const float			sfx		= (float)ix + 0.5f;
2384 			const float			sfy		= (float)iy + 0.5f;
2385 			const float			fx1		= deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
2386 			const float			fy1		= deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
2387 
2388 			// Triangle quad interpolation.
2389 			const bool			tri		= fx1 + fy1 <= 1.0f;
2390 			const float			tx		= tri ? fx1 : (1.0f-fx1);
2391 			const float			ty		= tri ? fy1 : (1.0f-fy1);
2392 			const tcu::Vec4&	t0		= tri ? c00 : c11;
2393 			const tcu::Vec4&	t1		= tri ? c01 : c10;
2394 			const tcu::Vec4&	t2		= tri ? c10 : c01;
2395 			const tcu::Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
2396 
2397 			result.setPixel(ix, iy, tcu::RGBA(color));
2398 		}
2399 	}
2400 }
2401 
computeFragmentReference(tcu::Surface & result,const QuadGrid & quadGrid)2402 void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
2403 {
2404 	DE_ASSERT(m_evaluator);
2405 
2406 	// Buffer info.
2407 	const int			width		= result.getWidth();
2408 	const int			height		= result.getHeight();
2409 	const bool			hasAlpha	= true;  // \todo [2015-09-07 elecro] add correct alpha check
2410 	ShaderEvalContext	evalCtx		(quadGrid);
2411 
2412 	// Render.
2413 	for (int y = 0; y < height; y++)
2414 	for (int x = 0; x < width; x++)
2415 	{
2416 		const float sx = ((float)x + 0.5f) / (float)width;
2417 		const float sy = ((float)y + 0.5f) / (float)height;
2418 
2419 		evalCtx.reset(sx, sy);
2420 		m_evaluator->evaluate(evalCtx);
2421 		// Select either clear color or computed color based on discarded bit.
2422 		tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
2423 
2424 		if (!hasAlpha)
2425 			color.w() = 1.0f;
2426 
2427 		result.setPixel(x, y, tcu::RGBA(color));
2428 	}
2429 }
2430 
compareImages(const tcu::Surface & resImage,const tcu::Surface & refImage,float errorThreshold)2431 bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
2432 {
2433 	return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_EVERYTHING);
2434 }
2435 
2436 } // sr
2437 } // vkt
2438