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 45 namespace vkt 46 { 47 namespace sr 48 { 49 50 class LineStream 51 { 52 public: 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 59 private: 60 int m_indent; 61 std::ostringstream m_stream; 62 mutable std::string m_string; 63 }; 64 65 class QuadGrid; 66 class ShaderRenderCaseInstance; 67 68 class TextureBinding 69 { 70 public: 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 141 private: 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 163 typedef de::SharedPtr<TextureBinding> TextureBindingSp; 164 165 // ShaderEvalContext. 166 167 class ShaderEvalContext 168 { 169 public: 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 221 private: 222 const QuadGrid& m_quadGrid; 223 }; 224 225 typedef void (*ShaderEvalFunc) (ShaderEvalContext& c); 226 227 inline void evalCoordsPassthroughX (ShaderEvalContext& c) { c.color.x() = c.coords.x(); } 228 inline void evalCoordsPassthroughXY (ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1); } 229 inline void evalCoordsPassthroughXYZ (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); } 230 inline void evalCoordsPassthrough (ShaderEvalContext& c) { c.color = c.coords; } 231 inline 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 236 class ShaderEvaluator 237 { 238 public: 239 ShaderEvaluator (void); 240 ShaderEvaluator (const ShaderEvalFunc evalFunc); 241 virtual ~ShaderEvaluator (void); 242 243 virtual void evaluate (ShaderEvalContext& ctx) const; 244 245 private: 246 ShaderEvaluator (const ShaderEvaluator&); // not allowed! 247 ShaderEvaluator& operator= (const ShaderEvaluator&); // not allowed! 248 249 const ShaderEvalFunc m_evalFunc; 250 }; 251 252 // UniformSetup 253 254 typedef void (*UniformSetupFunc) (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords); 255 256 class UniformSetup 257 { 258 public: 259 UniformSetup (void); 260 UniformSetup (const UniformSetupFunc setup); 261 virtual ~UniformSetup (void); 262 virtual void setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const; 263 264 private: 265 UniformSetup (const UniformSetup&); // not allowed! 266 UniformSetup& operator= (const UniformSetup&); // not allowed! 267 268 const UniformSetupFunc m_setupFunc; 269 }; 270 271 typedef void (*AttributeSetupFunc) (ShaderRenderCaseInstance& instance, deUint32 numVertices); 272 273 class ShaderRenderCase : public vkt::TestCase 274 { 275 public: 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 296 protected: 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 306 enum 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 409 enum 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 431 class ShaderRenderCaseInstance : public vkt::TestInstance 432 { 433 public: 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 476 protected: 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; 508 private: 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; 527 protected: 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 540 private: 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 586 private: 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 669 template<typename T> 670 void 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