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: 50 LineStream (int indent = 0) { m_indent = indent; } 51 ~LineStream (void) {} 52 53 const char* str (void) const { m_string = m_stream.str(); return m_string.c_str(); } 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); 84 Type getType (void) const { return m_type; } 85 const tcu::Sampler& getSampler (void) const { return m_sampler; } 86 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 125 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. 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 161 inline void evalCoordsPassthroughX (ShaderEvalContext& c) { c.color.x() = c.coords.x(); } 162 inline void evalCoordsPassthroughXY (ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1); } 163 inline void evalCoordsPassthroughXYZ (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); } 164 inline void evalCoordsPassthrough (ShaderEvalContext& c) { c.color = c.coords; } 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: 487 UniformInfo (void) {} 488 virtual ~UniformInfo (void) {} 489 490 vk::VkDescriptorType type; 491 deUint32 location; 492 }; 493 494 class BufferUniform : public UniformInfo 495 { 496 public: 497 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: 508 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> 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