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 "vkRefUtil.hpp"
36#include "vkPrograms.hpp"
37#include "vkRef.hpp"
38#include "vkMemUtil.hpp"
39#include "vkBuilderUtil.hpp"
40#include "vkTypeUtil.hpp"
41#include "vkPlatform.hpp"
42
43#include "vktTestCaseUtil.hpp"
44
45namespace vkt
46{
47namespace sr
48{
49
50class LineStream
51{
52public:
53						LineStream		(int indent = 0)	{ m_indent = indent; }
54						~LineStream		(void)				{}
55
56	const char*			str				(void) const		{ m_string = m_stream.str(); return m_string.c_str(); }
57	LineStream&			operator<<		(const char* line)	{ for (int i = 0; i < m_indent; i++) { m_stream << "\t"; } m_stream << line << "\n"; return *this; }
58
59private:
60	int					m_indent;
61	std::ostringstream	m_stream;
62	mutable std::string	m_string;
63};
64
65class QuadGrid;
66class ShaderRenderCaseInstance;
67
68class TextureBinding
69{
70public:
71	enum Type
72	{
73		TYPE_NONE = 0,
74		TYPE_1D,
75		TYPE_2D,
76		TYPE_3D,
77		TYPE_CUBE_MAP,
78		TYPE_1D_ARRAY,
79		TYPE_2D_ARRAY,
80		TYPE_CUBE_ARRAY,
81
82		TYPE_LAST
83	};
84
85	enum Init
86	{
87		INIT_UPLOAD_DATA,
88		INIT_CLEAR,
89
90		INIT_LAST
91	};
92
93	struct Parameters
94	{
95		deUint32					baseMipLevel;
96		vk::VkComponentMapping		componentMapping;
97		vk::VkSampleCountFlagBits	samples;
98		Init						initialization;
99
100		Parameters (deUint32					baseMipLevel_		= 0,
101					vk::VkComponentMapping		componentMapping_	= vk::makeComponentMappingRGBA(),
102					vk::VkSampleCountFlagBits	samples_			= vk::VK_SAMPLE_COUNT_1_BIT,
103					Init						initialization_		= INIT_UPLOAD_DATA)
104			: baseMipLevel		(baseMipLevel_)
105			, componentMapping	(componentMapping_)
106			, samples			(samples_)
107			, initialization	(initialization_)
108		{
109		}
110	};
111
112										TextureBinding		(const tcu::Archive&	archive,
113															const char*				filename,
114															const Type				type,
115															const tcu::Sampler&		sampler);
116
117										TextureBinding		(const tcu::Texture1D* tex1D, const tcu::Sampler& sampler);
118										TextureBinding		(const tcu::Texture2D* tex2D, const tcu::Sampler& sampler);
119										TextureBinding		(const tcu::Texture3D* tex3D, const tcu::Sampler& sampler);
120										TextureBinding		(const tcu::TextureCube* texCube, const tcu::Sampler& sampler);
121										TextureBinding		(const tcu::Texture1DArray* tex1DArray, const tcu::Sampler& sampler);
122										TextureBinding		(const tcu::Texture2DArray* tex2DArray, const tcu::Sampler& sampler);
123										TextureBinding		(const tcu::TextureCubeArray* texCubeArray, const tcu::Sampler& sampler);
124
125										~TextureBinding		(void);
126
127	Type								getType				(void) const { return m_type;		}
128	const tcu::Sampler&					getSampler			(void) const { return m_sampler;	}
129
130	const tcu::Texture1D&				get1D				(void) const { DE_ASSERT(getType() == TYPE_1D && m_binding.tex1D != NULL);					return *m_binding.tex1D;		}
131	const tcu::Texture2D&				get2D				(void) const { DE_ASSERT(getType() == TYPE_2D && m_binding.tex2D != NULL);					return *m_binding.tex2D;		}
132	const tcu::Texture3D&				get3D				(void) const { DE_ASSERT(getType() == TYPE_3D && m_binding.tex3D != NULL);					return *m_binding.tex3D;		}
133	const tcu::TextureCube&				getCube				(void) const { DE_ASSERT(getType() == TYPE_CUBE_MAP && m_binding.texCube != NULL);			return *m_binding.texCube;		}
134	const tcu::Texture1DArray&			get1DArray			(void) const { DE_ASSERT(getType() == TYPE_1D_ARRAY && m_binding.tex1DArray != NULL);		return *m_binding.tex1DArray;	}
135	const tcu::Texture2DArray&			get2DArray			(void) const { DE_ASSERT(getType() == TYPE_2D_ARRAY && m_binding.tex2DArray != NULL);		return *m_binding.tex2DArray;	}
136	const tcu::TextureCubeArray&		getCubeArray		(void) const { DE_ASSERT(getType() == TYPE_CUBE_ARRAY && m_binding.texCubeArray != NULL);	return *m_binding.texCubeArray;	}
137
138	void								setParameters		(const Parameters& params) { m_params = params; }
139	const Parameters&					getParameters		(void) const { return m_params; }
140
141private:
142										TextureBinding		(const TextureBinding&);	// not allowed!
143	TextureBinding&						operator=			(const TextureBinding&);	// not allowed!
144
145	static de::MovePtr<tcu::Texture2D>	loadTexture2D		(const tcu::Archive& archive, const char* filename);
146
147	Type								m_type;
148	tcu::Sampler						m_sampler;
149	Parameters							m_params;
150
151	union
152	{
153		const tcu::Texture1D*			tex1D;
154		const tcu::Texture2D*			tex2D;
155		const tcu::Texture3D*			tex3D;
156		const tcu::TextureCube*			texCube;
157		const tcu::Texture1DArray*		tex1DArray;
158		const tcu::Texture2DArray*		tex2DArray;
159		const tcu::TextureCubeArray*	texCubeArray;
160	} m_binding;
161};
162
163typedef de::SharedPtr<TextureBinding> TextureBindingSp;
164
165// ShaderEvalContext.
166
167class ShaderEvalContext
168{
169public:
170	// Limits.
171	enum
172	{
173		MAX_USER_ATTRIBS	= 4,
174		MAX_TEXTURES		= 4
175	};
176
177	struct ShaderSampler
178	{
179		tcu::Sampler					sampler;
180		const tcu::Texture1D*			tex1D;
181		const tcu::Texture2D*			tex2D;
182		const tcu::Texture3D*			tex3D;
183		const tcu::TextureCube*			texCube;
184		const tcu::Texture1DArray*		tex1DArray;
185		const tcu::Texture2DArray*		tex2DArray;
186		const tcu::TextureCubeArray*	texCubeArray;
187
188		inline ShaderSampler (void)
189			: tex1D			(DE_NULL)
190			, tex2D			(DE_NULL)
191			, tex3D			(DE_NULL)
192			, texCube		(DE_NULL)
193			, tex1DArray	(DE_NULL)
194			, tex2DArray	(DE_NULL)
195			, texCubeArray	(DE_NULL)
196		{
197		}
198	};
199
200							ShaderEvalContext		(const QuadGrid& quadGrid);
201							~ShaderEvalContext		(void);
202
203	void					reset					(float sx, float sy);
204
205	// Inputs.
206	tcu::Vec4				coords;
207	tcu::Vec4				unitCoords;
208	tcu::Vec4				constCoords;
209
210	tcu::Vec4				in[MAX_USER_ATTRIBS];
211	ShaderSampler			textures[MAX_TEXTURES];
212
213	// Output.
214	tcu::Vec4				color;
215	bool					isDiscarded;
216
217	// Functions.
218	inline void				discard					(void)  { isDiscarded = true; }
219	tcu::Vec4				texture2D				(int unitNdx, const tcu::Vec2& coords);
220
221private:
222	const QuadGrid&			m_quadGrid;
223};
224
225typedef void (*ShaderEvalFunc) (ShaderEvalContext& c);
226
227inline void evalCoordsPassthroughX		(ShaderEvalContext& c) { c.color.x() = c.coords.x(); }
228inline void evalCoordsPassthroughXY		(ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1); }
229inline void evalCoordsPassthroughXYZ	(ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
230inline void evalCoordsPassthrough		(ShaderEvalContext& c) { c.color = c.coords; }
231inline void evalCoordsSwizzleWZYX		(ShaderEvalContext& c) { c.color = c.coords.swizzle(3,2,1,0); }
232
233// ShaderEvaluator
234// Either inherit a class with overridden evaluate() or just pass in an evalFunc.
235
236class ShaderEvaluator
237{
238public:
239							ShaderEvaluator			(void);
240							ShaderEvaluator			(const ShaderEvalFunc evalFunc);
241	virtual					~ShaderEvaluator		(void);
242
243	virtual void			evaluate				(ShaderEvalContext& ctx) const;
244
245private:
246							ShaderEvaluator			(const ShaderEvaluator&);   // not allowed!
247	ShaderEvaluator&		operator=				(const ShaderEvaluator&);   // not allowed!
248
249	const ShaderEvalFunc	m_evalFunc;
250};
251
252// UniformSetup
253
254typedef void (*UniformSetupFunc) (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords);
255
256class UniformSetup
257{
258public:
259							UniformSetup			(void);
260							UniformSetup			(const UniformSetupFunc setup);
261	virtual					~UniformSetup			(void);
262	virtual void			setup					(ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const;
263
264private:
265							UniformSetup			(const UniformSetup&);	// not allowed!
266	UniformSetup&			operator=				(const UniformSetup&);	// not allowed!
267
268	const UniformSetupFunc	m_setupFunc;
269};
270
271typedef void (*AttributeSetupFunc) (ShaderRenderCaseInstance& instance, deUint32 numVertices);
272
273class ShaderRenderCase : public vkt::TestCase
274{
275public:
276													ShaderRenderCase	(tcu::TestContext&			testCtx,
277																		 const std::string&			name,
278																		 const std::string&			description,
279																		 const bool					isVertexCase,
280																		 const ShaderEvalFunc		evalFunc,
281																		 const UniformSetup*		uniformSetup,
282																		 const AttributeSetupFunc	attribFunc);
283
284													ShaderRenderCase	(tcu::TestContext&			testCtx,
285																		 const std::string&			name,
286																		 const std::string&			description,
287																		 const bool					isVertexCase,
288																		 const ShaderEvaluator*		evaluator,
289																		 const UniformSetup*		uniformSetup,
290																		 const AttributeSetupFunc	attribFunc);
291
292	virtual											~ShaderRenderCase	(void);
293	virtual	void									initPrograms		(vk::SourceCollections& programCollection) const;
294	virtual	TestInstance*							createInstance		(Context& context) const;
295
296protected:
297	std::string										m_vertShaderSource;
298	std::string										m_fragShaderSource;
299
300	const bool										m_isVertexCase;
301	const de::UniquePtr<const ShaderEvaluator>		m_evaluator;
302	const de::UniquePtr<const UniformSetup>			m_uniformSetup;
303	const AttributeSetupFunc						m_attribFunc;
304};
305
306enum BaseUniformType
307{
308// Bool
309	UB_FALSE,
310	UB_TRUE,
311
312// BVec4
313	UB4_FALSE,
314	UB4_TRUE,
315
316// Integers
317	UI_ZERO,
318	UI_ONE,
319	UI_TWO,
320	UI_THREE,
321	UI_FOUR,
322	UI_FIVE,
323	UI_SIX,
324	UI_SEVEN,
325	UI_EIGHT,
326	UI_ONEHUNDREDONE,
327
328// IVec2
329	UI2_MINUS_ONE,
330	UI2_ZERO,
331	UI2_ONE,
332	UI2_TWO,
333	UI2_THREE,
334	UI2_FOUR,
335	UI2_FIVE,
336
337// IVec3
338	UI3_MINUS_ONE,
339	UI3_ZERO,
340	UI3_ONE,
341	UI3_TWO,
342	UI3_THREE,
343	UI3_FOUR,
344	UI3_FIVE,
345
346// IVec4
347	UI4_MINUS_ONE,
348	UI4_ZERO,
349	UI4_ONE,
350	UI4_TWO,
351	UI4_THREE,
352	UI4_FOUR,
353	UI4_FIVE,
354
355// Float
356	UF_ZERO,
357	UF_ONE,
358	UF_TWO,
359	UF_THREE,
360	UF_FOUR,
361	UF_FIVE,
362	UF_SIX,
363	UF_SEVEN,
364	UF_EIGHT,
365
366	UF_HALF,
367	UF_THIRD,
368	UF_FOURTH,
369	UF_FIFTH,
370	UF_SIXTH,
371	UF_SEVENTH,
372	UF_EIGHTH,
373
374// Vec2
375	UV2_MINUS_ONE,
376	UV2_ZERO,
377	UV2_ONE,
378	UV2_TWO,
379	UV2_THREE,
380
381	UV2_HALF,
382
383// Vec3
384	UV3_MINUS_ONE,
385	UV3_ZERO,
386	UV3_ONE,
387	UV3_TWO,
388	UV3_THREE,
389
390	UV3_HALF,
391
392// Vec4
393	UV4_MINUS_ONE,
394	UV4_ZERO,
395	UV4_ONE,
396	UV4_TWO,
397	UV4_THREE,
398
399	UV4_HALF,
400
401	UV4_BLACK,
402	UV4_GRAY,
403	UV4_WHITE,
404
405// Last
406	U_LAST
407};
408
409enum BaseAttributeType
410{
411// User attributes
412	A_IN0,
413	A_IN1,
414	A_IN2,
415	A_IN3,
416
417// Matrices
418	MAT2,
419	MAT2x3,
420	MAT2x4,
421	MAT3x2,
422	MAT3,
423	MAT3x4,
424	MAT4x2,
425	MAT4x3,
426	MAT4
427};
428
429// ShaderRenderCaseInstance.
430
431class ShaderRenderCaseInstance : public vkt::TestInstance
432{
433public:
434	enum ImageBackingMode
435	{
436		IMAGE_BACKING_MODE_REGULAR = 0,
437		IMAGE_BACKING_MODE_SPARSE,
438	};
439
440														ShaderRenderCaseInstance	(Context&					context);
441														ShaderRenderCaseInstance	(Context&					context,
442																					const bool					isVertexCase,
443																					const ShaderEvaluator&		evaluator,
444																					const UniformSetup&			uniformSetup,
445																					const AttributeSetupFunc	attribFunc,
446																					const ImageBackingMode		imageBackingMode = IMAGE_BACKING_MODE_REGULAR);
447
448	virtual												~ShaderRenderCaseInstance	(void);
449	virtual tcu::TestStatus								iterate						(void);
450
451	void												addAttribute				(deUint32			bindingLocation,
452																					vk::VkFormat		format,
453																					deUint32			sizePerElement,
454																					deUint32			count,
455																					const void*			data);
456	void												useAttribute				(deUint32			bindingLocation,
457																					BaseAttributeType	type);
458
459	template<typename T>
460	void												addUniform					(deUint32				bindingLocation,
461																					vk::VkDescriptorType	descriptorType,
462																					const T&				data);
463	void												addUniform					(deUint32				bindingLocation,
464																					vk::VkDescriptorType	descriptorType,
465																					size_t					dataSize,
466																					const void*				data);
467	void												useUniform					(deUint32				bindingLocation,
468																					BaseUniformType			type);
469	void												useSampler					(deUint32				bindingLocation,
470																					deUint32				textureId);
471
472	static const tcu::Vec4								getDefaultConstCoords		(void) { return tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f); }
473	void												setPushConstantRanges		(const deUint32 rangeCount, const vk::VkPushConstantRange* const pcRanges);
474	virtual void										updatePushConstants			(vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout);
475
476protected:
477														ShaderRenderCaseInstance	(Context&					context,
478																					 const bool					isVertexCase,
479																					 const ShaderEvaluator*		evaluator,
480																					 const UniformSetup*		uniformSetup,
481																					 const AttributeSetupFunc	attribFunc,
482																					 const ImageBackingMode		imageBackingMode = IMAGE_BACKING_MODE_REGULAR);
483
484	virtual void										setup						(void);
485	virtual void										setupUniforms				(const tcu::Vec4& constCoords);
486	virtual void										setupDefaultInputs			(void);
487
488	void												render						(deUint32					numVertices,
489																					 deUint32					numTriangles,
490																					 const deUint16*			indices,
491																					 const tcu::Vec4&			constCoords		= getDefaultConstCoords());
492
493	void												render						(deUint32					numVertices,
494																					 deUint32					numIndices,
495																					 const deUint16*			indices,
496																					 vk::VkPrimitiveTopology	topology,
497																					 const tcu::Vec4&			constCoords		= getDefaultConstCoords());
498
499	const tcu::TextureLevel&							getResultImage				(void) const { return m_resultImage; }
500
501	const tcu::UVec2									getViewportSize				(void) const;
502
503	void												setSampleCount				(vk::VkSampleCountFlagBits sampleCount);
504
505	bool												isMultiSampling				(void) const;
506
507	ImageBackingMode									m_imageBackingMode;
508private:
509
510	struct SparseContext
511	{
512											SparseContext	(vkt::Context& context);
513
514		vkt::Context&						m_context;
515		const deUint32						m_queueFamilyIndex;
516		vk::Unique<vk::VkDevice>			m_device;
517		vk::DeviceDriver					m_deviceInterface;
518		vk::VkQueue							m_queue;
519		const de::UniquePtr<vk::Allocator>	m_allocator;
520	private:
521		vk::Move<vk::VkDevice>				createDevice	(void) const;
522		vk::Allocator*						createAllocator	(void) const;
523
524	};
525
526	de::UniquePtr<SparseContext>						m_sparseContext;
527protected:
528	vk::Allocator&										m_memAlloc;
529	const tcu::Vec4										m_clearColor;
530	const bool											m_isVertexCase;
531
532	std::vector<tcu::Mat4>								m_userAttribTransforms;
533	std::vector<TextureBindingSp>						m_textures;
534
535	std::string											m_vertexShaderName;
536	std::string											m_fragmentShaderName;
537	tcu::UVec2											m_renderSize;
538	vk::VkFormat										m_colorFormat;
539
540private:
541	typedef std::vector<tcu::ConstPixelBufferAccess>	TextureLayerData;
542	typedef std::vector<TextureLayerData>				TextureData;
543
544	void												uploadImage					(const tcu::TextureFormat&		texFormat,
545																					 const TextureData&				textureData,
546																					 const tcu::Sampler&			refSampler,
547																					 deUint32						mipLevels,
548																					 deUint32						arrayLayers,
549																					 vk::VkImage					destImage);
550
551	void												clearImage					(const tcu::Sampler&			refSampler,
552																					 deUint32						mipLevels,
553																					 deUint32						arrayLayers,
554																					 vk::VkImage					destImage);
555
556	void												checkSparseSupport			(const vk::VkImageType imageType) const;
557
558	void												uploadSparseImage			(const tcu::TextureFormat&		texFormat,
559																					 const TextureData&				textureData,
560																					 const tcu::Sampler&			refSampler,
561																					 const deUint32					mipLevels,
562																					 const deUint32					arrayLayers,
563																					 const vk::VkImage				sparseImage,
564																					 const vk::VkImageCreateInfo&	imageCreateInfo,
565																					 const tcu::UVec3				texSize);
566
567	void												createSamplerUniform		(deUint32						bindingLocation,
568																					 TextureBinding::Type			textureType,
569																					 TextureBinding::Init			textureInit,
570																					 const tcu::TextureFormat&		texFormat,
571																					 const tcu::UVec3				texSize,
572																					 const TextureData&				textureData,
573																					 const tcu::Sampler&			refSampler,
574																					 deUint32						mipLevels,
575																					 deUint32						arrayLayers,
576																					 TextureBinding::Parameters		textureParams);
577
578	void												setupUniformData			(deUint32 bindingLocation, size_t size, const void* dataPtr);
579
580	void												computeVertexReference		(tcu::Surface& result, const QuadGrid& quadGrid);
581	void												computeFragmentReference	(tcu::Surface& result, const QuadGrid& quadGrid);
582	bool												compareImages				(const tcu::Surface&	resImage,
583																					 const tcu::Surface&	refImage,
584																					 float					errorThreshold);
585
586private:
587	const ShaderEvaluator*								m_evaluator;
588	const UniformSetup*									m_uniformSetup;
589	const AttributeSetupFunc							m_attribFunc;
590	de::MovePtr<QuadGrid>								m_quadGrid;
591	tcu::TextureLevel									m_resultImage;
592
593	struct EnabledBaseAttribute
594	{
595		deUint32			location;
596		BaseAttributeType	type;
597	};
598	std::vector<EnabledBaseAttribute>					m_enabledBaseAttributes;
599
600	de::MovePtr<vk::DescriptorSetLayoutBuilder>			m_descriptorSetLayoutBuilder;
601	de::MovePtr<vk::DescriptorPoolBuilder>				m_descriptorPoolBuilder;
602	de::MovePtr<vk::DescriptorSetUpdateBuilder>			m_descriptorSetUpdateBuilder;
603
604	typedef de::SharedPtr<vk::Unique<vk::VkBuffer> >		VkBufferSp;
605	typedef de::SharedPtr<vk::Unique<vk::VkImage> >			VkImageSp;
606	typedef de::SharedPtr<vk::Unique<vk::VkImageView> >		VkImageViewSp;
607	typedef de::SharedPtr<vk::Unique<vk::VkSampler> >		VkSamplerSp;
608	typedef de::SharedPtr<vk::Allocation>					AllocationSp;
609
610	class UniformInfo
611	{
612	public:
613									UniformInfo		(void) {}
614		virtual						~UniformInfo	(void) {}
615
616		vk::VkDescriptorType		type;
617		deUint32					location;
618	};
619
620	class BufferUniform : public UniformInfo
621	{
622	public:
623									BufferUniform	(void) {}
624		virtual						~BufferUniform	(void) {}
625
626		VkBufferSp					buffer;
627		AllocationSp				alloc;
628		vk::VkDescriptorBufferInfo	descriptor;
629	};
630
631	class SamplerUniform : public UniformInfo
632	{
633	public:
634									SamplerUniform	(void) {}
635		virtual						~SamplerUniform	(void) {}
636
637		VkImageSp					image;
638		VkImageViewSp				imageView;
639		VkSamplerSp					sampler;
640		AllocationSp				alloc;
641		vk::VkDescriptorImageInfo	descriptor;
642	};
643
644	typedef de::SharedPtr<de::UniquePtr<UniformInfo> >	UniformInfoSp;
645	std::vector<UniformInfoSp>							m_uniformInfos;
646
647	std::vector< de::SharedPtr<vk::Allocation> >		m_allocations;
648
649	std::vector<vk::VkVertexInputBindingDescription>	m_vertexBindingDescription;
650	std::vector<vk::VkVertexInputAttributeDescription>	m_vertexAttributeDescription;
651
652	std::vector<VkBufferSp>								m_vertexBuffers;
653	std::vector<AllocationSp>							m_vertexBufferAllocs;
654
655	vk::VkSampleCountFlagBits							m_sampleCount;
656	std::vector<vk::VkPushConstantRange>				m_pushConstantRanges;
657
658	// Wrapper functions around m_context calls to support sparse cases.
659	vk::VkDevice										getDevice						(void) const;
660	deUint32											getUniversalQueueFamilyIndex	(void) const;
661	const vk::DeviceInterface&							getDeviceInterface				(void) const;
662	vk::VkQueue											getUniversalQueue				(void) const;
663	vk::VkPhysicalDevice								getPhysicalDevice				(void) const;
664	const vk::InstanceInterface&						getInstanceInterface			(void) const;
665	SparseContext*										createSparseContext				(void) const;
666	vk::Allocator&										getAllocator					(void) const;
667};
668
669template<typename T>
670void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, const T& data)
671{
672	addUniform(bindingLocation, descriptorType, sizeof(T), &data);
673}
674
675} // sr
676} // vkt
677
678#endif // _VKTSHADERRENDER_HPP
679