1 #ifndef _VKTSHADERRENDER_HPP
2 #define _VKTSHADERRENDER_HPP
3 /*------------------------------------------------------------------------
4  * Vulkan Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2015 The Khronos Group Inc.
8  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Vulkan ShaderRenderCase
25  *//*--------------------------------------------------------------------*/
26 
27 #include "tcuTexture.hpp"
28 #include "tcuSurface.hpp"
29 
30 #include "deMemory.h"
31 #include "deSharedPtr.hpp"
32 #include "deUniquePtr.hpp"
33 
34 #include "vkDefs.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkRef.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 
40 #include "vktTestCaseUtil.hpp"
41 
42 namespace vkt
43 {
44 namespace sr
45 {
46 
47 class LineStream
48 {
49 public:
LineStream(int indent=0)50 						LineStream		(int indent = 0)	{ m_indent = indent; }
~LineStream(void)51 						~LineStream		(void)				{}
52 
str(void) const53 	const char*			str				(void) const		{ m_string = m_stream.str(); return m_string.c_str(); }
operator <<(const char * line)54 	LineStream&			operator<<		(const char* line)	{ for (int i = 0; i < m_indent; i++) { m_stream << "\t"; } m_stream << line << "\n"; return *this; }
55 
56 private:
57 	int					m_indent;
58 	std::ostringstream	m_stream;
59 	mutable std::string	m_string;
60 };
61 
62 class QuadGrid;
63 class ShaderRenderCaseInstance;
64 
65 class TextureBinding
66 {
67 public:
68 	enum Type
69 	{
70 		TYPE_NONE = 0,
71 		TYPE_2D,
72 		TYPE_CUBE_MAP,
73 		TYPE_2D_ARRAY,
74 		TYPE_3D,
75 
76 		TYPE_LAST
77 	};
78 
79 										TextureBinding		(const tcu::Archive&	archive,
80 															const char*				filename,
81 															const Type				type,
82 															const tcu::Sampler&		sampler);
83 										~TextureBinding		(void);
getType(void) const84 	Type								getType				(void) const { return m_type;		}
getSampler(void) const85 	const tcu::Sampler&					getSampler			(void) const { return m_sampler;	}
get2D(void) const86 	const tcu::Texture2D&				get2D				(void) const { DE_ASSERT(getType() == TYPE_2D && m_binding.tex2D !=NULL); return *m_binding.tex2D; }
87 
88 private:
89 										TextureBinding		(const TextureBinding&);	// not allowed!
90 	TextureBinding&						operator=			(const TextureBinding&);	// not allowed!
91 
92 	static de::MovePtr<tcu::Texture2D>	loadTexture2D		(const tcu::Archive& archive, const char* filename);
93 
94 	Type								m_type;
95 	tcu::Sampler						m_sampler;
96 
97 	union
98 	{
99 		const tcu::Texture2D*	tex2D;
100 	} m_binding;
101 };
102 
103 typedef de::SharedPtr<TextureBinding> TextureBindingSp;
104 
105 // ShaderEvalContext.
106 
107 class ShaderEvalContext
108 {
109 public:
110 	// Limits.
111 	enum
112 	{
113 		MAX_USER_ATTRIBS	= 4,
114 		MAX_TEXTURES		= 4
115 	};
116 
117 	struct ShaderSampler
118 	{
119 		tcu::Sampler				sampler;
120 		const tcu::Texture2D*		tex2D;
121 		const tcu::TextureCube*		texCube;
122 		const tcu::Texture2DArray*	tex2DArray;
123 		const tcu::Texture3D*		tex3D;
124 
ShaderSamplervkt::sr::ShaderEvalContext::ShaderSampler125 		inline ShaderSampler (void)
126 			: tex2D		(DE_NULL)
127 			, texCube	(DE_NULL)
128 			, tex2DArray(DE_NULL)
129 			, tex3D		(DE_NULL)
130 		{
131 		}
132 	};
133 
134 							ShaderEvalContext		(const QuadGrid& quadGrid);
135 							~ShaderEvalContext		(void);
136 
137 	void					reset					(float sx, float sy);
138 
139 	// Inputs.
140 	tcu::Vec4				coords;
141 	tcu::Vec4				unitCoords;
142 	tcu::Vec4				constCoords;
143 
144 	tcu::Vec4				in[MAX_USER_ATTRIBS];
145 	ShaderSampler			textures[MAX_TEXTURES];
146 
147 	// Output.
148 	tcu::Vec4				color;
149 	bool					isDiscarded;
150 
151 	// Functions.
discard(void)152 	inline void				discard					(void)  { isDiscarded = true; }
153 	tcu::Vec4				texture2D				(int unitNdx, const tcu::Vec2& coords);
154 
155 private:
156 	const QuadGrid&			m_quadGrid;
157 };
158 
159 typedef void (*ShaderEvalFunc) (ShaderEvalContext& c);
160 
evalCoordsPassthroughX(ShaderEvalContext & c)161 inline void evalCoordsPassthroughX		(ShaderEvalContext& c) { c.color.x() = c.coords.x(); }
evalCoordsPassthroughXY(ShaderEvalContext & c)162 inline void evalCoordsPassthroughXY		(ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1); }
evalCoordsPassthroughXYZ(ShaderEvalContext & c)163 inline void evalCoordsPassthroughXYZ	(ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
evalCoordsPassthrough(ShaderEvalContext & c)164 inline void evalCoordsPassthrough		(ShaderEvalContext& c) { c.color = c.coords; }
evalCoordsSwizzleWZYX(ShaderEvalContext & c)165 inline void evalCoordsSwizzleWZYX		(ShaderEvalContext& c) { c.color = c.coords.swizzle(3,2,1,0); }
166 
167 // ShaderEvaluator
168 // Either inherit a class with overridden evaluate() or just pass in an evalFunc.
169 
170 class ShaderEvaluator
171 {
172 public:
173 							ShaderEvaluator			(void);
174 							ShaderEvaluator			(const ShaderEvalFunc evalFunc);
175 	virtual					~ShaderEvaluator		(void);
176 
177 	virtual void			evaluate				(ShaderEvalContext& ctx) const;
178 
179 private:
180 							ShaderEvaluator			(const ShaderEvaluator&);   // not allowed!
181 	ShaderEvaluator&		operator=				(const ShaderEvaluator&);   // not allowed!
182 
183 	const ShaderEvalFunc	m_evalFunc;
184 };
185 
186 // UniformSetup
187 
188 typedef void (*UniformSetupFunc) (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords);
189 
190 class UniformSetup
191 {
192 public:
193 							UniformSetup			(void);
194 							UniformSetup			(const UniformSetupFunc setup);
195 	virtual					~UniformSetup			(void);
196 	virtual void			setup					(ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const;
197 
198 private:
199 							UniformSetup			(const UniformSetup&);	// not allowed!
200 	UniformSetup&			operator=				(const UniformSetup&);	// not allowed!
201 
202 	const UniformSetupFunc	m_setupFunc;
203 };
204 
205 typedef void (*AttributeSetupFunc) (ShaderRenderCaseInstance& instance, deUint32 numVertices);
206 
207 class ShaderRenderCase : public vkt::TestCase
208 {
209 public:
210 													ShaderRenderCase	(tcu::TestContext&			testCtx,
211 																		 const std::string&			name,
212 																		 const std::string&			description,
213 																		 const bool					isVertexCase,
214 																		 const ShaderEvalFunc		evalFunc,
215 																		 const UniformSetup*		uniformSetup,
216 																		 const AttributeSetupFunc	attribFunc);
217 
218 													ShaderRenderCase	(tcu::TestContext&			testCtx,
219 																		 const std::string&			name,
220 																		 const std::string&			description,
221 																		 const bool					isVertexCase,
222 																		 const ShaderEvaluator*		evaluator,
223 																		 const UniformSetup*		uniformSetup,
224 																		 const AttributeSetupFunc	attribFunc);
225 
226 
227 	virtual											~ShaderRenderCase	(void);
228 	virtual	void									initPrograms		(vk::SourceCollections& programCollection) const;
229 	virtual	TestInstance*							createInstance		(Context& context) const;
230 
231 protected:
232 	std::string										m_vertShaderSource;
233 	std::string										m_fragShaderSource;
234 
235 	const bool										m_isVertexCase;
236 	const de::UniquePtr<const ShaderEvaluator>		m_evaluator;
237 	const de::UniquePtr<const UniformSetup>			m_uniformSetup;
238 	const AttributeSetupFunc						m_attribFunc;
239 };
240 
241 
242 enum BaseUniformType
243 {
244 // Bool
245 	UB_FALSE,
246 	UB_TRUE,
247 
248 // BVec4
249 	UB4_FALSE,
250 	UB4_TRUE,
251 
252 // Integers
253 	UI_ZERO,
254 	UI_ONE,
255 	UI_TWO,
256 	UI_THREE,
257 	UI_FOUR,
258 	UI_FIVE,
259 	UI_SIX,
260 	UI_SEVEN,
261 	UI_EIGHT,
262 	UI_ONEHUNDREDONE,
263 
264 // IVec2
265 	UI2_MINUS_ONE,
266 	UI2_ZERO,
267 	UI2_ONE,
268 	UI2_TWO,
269 	UI2_THREE,
270 	UI2_FOUR,
271 	UI2_FIVE,
272 
273 // IVec3
274 	UI3_MINUS_ONE,
275 	UI3_ZERO,
276 	UI3_ONE,
277 	UI3_TWO,
278 	UI3_THREE,
279 	UI3_FOUR,
280 	UI3_FIVE,
281 
282 // IVec4
283 	UI4_MINUS_ONE,
284 	UI4_ZERO,
285 	UI4_ONE,
286 	UI4_TWO,
287 	UI4_THREE,
288 	UI4_FOUR,
289 	UI4_FIVE,
290 
291 // Float
292 	UF_ZERO,
293 	UF_ONE,
294 	UF_TWO,
295 	UF_THREE,
296 	UF_FOUR,
297 	UF_FIVE,
298 	UF_SIX,
299 	UF_SEVEN,
300 	UF_EIGHT,
301 
302 	UF_HALF,
303 	UF_THIRD,
304 	UF_FOURTH,
305 	UF_FIFTH,
306 	UF_SIXTH,
307 	UF_SEVENTH,
308 	UF_EIGHTH,
309 
310 // Vec2
311 	UV2_MINUS_ONE,
312 	UV2_ZERO,
313 	UV2_ONE,
314 	UV2_TWO,
315 	UV2_THREE,
316 
317 	UV2_HALF,
318 
319 // Vec3
320 	UV3_MINUS_ONE,
321 	UV3_ZERO,
322 	UV3_ONE,
323 	UV3_TWO,
324 	UV3_THREE,
325 
326 	UV3_HALF,
327 
328 // Vec4
329 	UV4_MINUS_ONE,
330 	UV4_ZERO,
331 	UV4_ONE,
332 	UV4_TWO,
333 	UV4_THREE,
334 
335 	UV4_HALF,
336 
337 	UV4_BLACK,
338 	UV4_GRAY,
339 	UV4_WHITE
340 };
341 
342 enum BaseAttributeType
343 {
344 // User attributes
345 	A_IN0,
346 	A_IN1,
347 	A_IN2,
348 	A_IN3,
349 
350 // Matrices
351 	MAT2,
352 	MAT2x3,
353 	MAT2x4,
354 	MAT3x2,
355 	MAT3,
356 	MAT3x4,
357 	MAT4x2,
358 	MAT4x3,
359 	MAT4
360 };
361 
362 // ShaderRenderCaseInstance.
363 
364 class ShaderRenderCaseInstance : public vkt::TestInstance
365 {
366 public:
367 														ShaderRenderCaseInstance	(Context&					context,
368 																					const bool					isVertexCase,
369 																					const ShaderEvaluator&		evaluator,
370 																					const UniformSetup&			uniformSetup,
371 																					const AttributeSetupFunc	attribFunc);
372 
373 	virtual												~ShaderRenderCaseInstance	(void);
374 	virtual tcu::TestStatus								iterate						(void);
375 
376 	void												addAttribute				(deUint32			bindingLocation,
377 																					vk::VkFormat		format,
378 																					deUint32			sizePerElement,
379 																					deUint32			count,
380 																					const void*			data);
381 	void												useAttribute				(deUint32			bindingLocation,
382 																					BaseAttributeType	type);
383 
384 	template<typename T>
385 	void												addUniform					(deUint32				bindingLocation,
386 																					vk::VkDescriptorType	descriptorType,
387 																					const T&				data);
388 	void												addUniform					(deUint32				bindingLocation,
389 																					vk::VkDescriptorType	descriptorType,
390 																					size_t					dataSize,
391 																					const void*				data);
392 	void												useUniform					(deUint32				bindingLocation,
393 																					BaseUniformType			type);
394 	void												useSampler2D				(deUint32				bindingLocation,
395 																					deUint32				textureId);
396 
397 protected:
398 	virtual void										setup						(void);
399 	virtual void										setupUniforms				(const tcu::Vec4& constCoords);
400 
401 	const tcu::UVec2									getViewportSize				(void) const;
402 
403 	std::vector<tcu::Mat4>								m_userAttribTransforms;
404 	const tcu::Vec4										m_clearColor;
405 	std::vector<TextureBindingSp>						m_textures;
406 
407 	vk::Allocator&										m_memAlloc;
408 
409 private:
410 
411 	void												setupTextures				(void);
412 	de::MovePtr<vk::Allocation>							uploadImage2D				(const tcu::Texture2D&			refTexture,
413 																					 const vk::VkImage&				vkTexture);
414 	vk::Move<vk::VkImage>								createImage2D				(const tcu::Texture2D&			texture,
415 																					 const vk::VkFormat				format,
416 																					 const vk::VkImageUsageFlags	usage,
417 																					 const vk::VkImageTiling		tiling);
418 	void												copyTilingImageToOptimal	(const vk::VkImage&				srcImage,
419 																					 const vk::VkImage&				dstImage,
420 																					 deUint32						width,
421 																					 deUint32						height);
422 
423 	void												setupUniformData			(deUint32 bindingLocation, size_t size, const void* dataPtr);
424 	void												setupDefaultInputs			(const QuadGrid& quadGrid);
425 
426 	void												render						(tcu::Surface& result, const QuadGrid& quadGrid);
427 	void												computeVertexReference		(tcu::Surface& result, const QuadGrid& quadGrid);
428 	void												computeFragmentReference	(tcu::Surface& result, const QuadGrid& quadGrid);
429 	bool												compareImages				(const tcu::Surface&	resImage,
430 																					 const tcu::Surface&	refImage,
431 																					 float					errorThreshold);
432 
433 	const bool											m_isVertexCase;
434 	const ShaderEvaluator&								m_evaluator;
435 	const UniformSetup&									m_uniformSetup;
436 	const AttributeSetupFunc							m_attribFunc;
437 
438 	struct EnabledBaseAttribute
439 	{
440 		deUint32			location;
441 		BaseAttributeType	type;
442 	};
443 	std::vector<EnabledBaseAttribute>					m_enabledBaseAttributes;
444 
445 	const tcu::UVec2									m_renderSize;
446 	const vk::VkFormat									m_colorFormat;
447 
448 	vk::Move<vk::VkImage>								m_colorImage;
449 	de::MovePtr<vk::Allocation>							m_colorImageAlloc;
450 	vk::Move<vk::VkImageView>							m_colorImageView;
451 
452 	vk::Move<vk::VkRenderPass>							m_renderPass;
453 	vk::Move<vk::VkFramebuffer>							m_framebuffer;
454 	vk::Move<vk::VkPipelineLayout>						m_pipelineLayout;
455 	vk::Move<vk::VkPipeline>							m_graphicsPipeline;
456 
457 	vk::Move<vk::VkShaderModule>						m_vertexShaderModule;
458 	vk::Move<vk::VkShaderModule>						m_fragmentShaderModule;
459 
460 	vk::Move<vk::VkBuffer>								m_indiceBuffer;
461 	de::MovePtr<vk::Allocation>							m_indiceBufferAlloc;
462 
463 	vk::Move<vk::VkDescriptorSetLayout>					m_descriptorSetLayout;
464 
465 	vk::Move<vk::VkDescriptorPool>						m_descriptorPool;
466 	vk::Move<vk::VkDescriptorSet>						m_descriptorSet;
467 
468 	vk::Move<vk::VkCommandPool>							m_cmdPool;
469 	vk::Move<vk::VkCommandBuffer>						m_cmdBuffer;
470 
471 	vk::Move<vk::VkFence>								m_fence;
472 
473 	vk::DescriptorSetLayoutBuilder						m_descriptorSetLayoutBuilder;
474 	vk::DescriptorPoolBuilder							m_descriptorPoolBuilder;
475 	vk::DescriptorSetUpdateBuilder						m_descriptorSetUpdateBuilder;
476 
477 	typedef de::SharedPtr<vk::Unique<vk::VkBuffer> >		VkBufferSp;
478 
479 	typedef de::SharedPtr<vk::Unique<vk::VkImage> >			VkImageSp;
480 	typedef de::SharedPtr<vk::Unique<vk::VkImageView> >		VkImageViewSp;
481 	typedef de::SharedPtr<vk::Unique<vk::VkSampler> >		VkSamplerSp;
482 	typedef de::SharedPtr<vk::Allocation>					AllocationSp;
483 
484 	class UniformInfo
485 	{
486 	public:
UniformInfo(void)487 									UniformInfo		(void) {}
~UniformInfo(void)488 		virtual						~UniformInfo	(void) {}
489 
490 		vk::VkDescriptorType		type;
491 		deUint32					location;
492 	};
493 
494 	class BufferUniform : public UniformInfo
495 	{
496 	public:
BufferUniform(void)497 									BufferUniform	(void) {}
~BufferUniform(void)498 		virtual						~BufferUniform	(void) {}
499 
500 		VkBufferSp					buffer;
501 		AllocationSp				alloc;
502 		vk::VkDescriptorBufferInfo	descriptor;
503 	};
504 
505 	class SamplerUniform : public UniformInfo
506 	{
507 	public:
SamplerUniform(void)508 									SamplerUniform	(void) {}
~SamplerUniform(void)509 		virtual						~SamplerUniform	(void) {}
510 
511 		VkImageSp					image;
512 		VkImageViewSp				imageView;
513 		VkSamplerSp					sampler;
514 		AllocationSp				alloc;
515 		vk::VkDescriptorImageInfo	descriptor;
516 	};
517 
518 	typedef de::SharedPtr<de::UniquePtr<UniformInfo> >	UniformInfoSp;
519 	std::vector<UniformInfoSp>							m_uniformInfos;
520 
521 	std::vector<vk::VkVertexInputBindingDescription>	m_vertexBindingDescription;
522 	std::vector<vk::VkVertexInputAttributeDescription>	m_vertexattributeDescription;
523 
524 	std::vector<VkBufferSp>								m_vertexBuffers;
525 	std::vector<AllocationSp>							m_vertexBufferAllocs;
526 };
527 
528 template<typename T>
addUniform(deUint32 bindingLocation,vk::VkDescriptorType descriptorType,const T & data)529 void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, const T& data)
530 {
531 	addUniform(bindingLocation, descriptorType, sizeof(T), &data);
532 }
533 
534 } // sr
535 } // vkt
536 
537 #endif // _VKTSHADERRENDER_HPP
538