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