1 #ifndef _VKTTESSELLATIONUTIL_HPP 2 #define _VKTTESSELLATIONUTIL_HPP 3 /*------------------------------------------------------------------------ 4 * Vulkan Conformance Tests 5 * ------------------------ 6 * 7 * Copyright (c) 2014 The Android Open Source Project 8 * Copyright (c) 2016 The Khronos Group Inc. 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 Tessellation Utilities 25 *//*--------------------------------------------------------------------*/ 26 27 #include "vkDefs.hpp" 28 #include "vkMemUtil.hpp" 29 #include "vkRef.hpp" 30 #include "vkPrograms.hpp" 31 #include "vkRefUtil.hpp" 32 #include "vkQueryUtil.hpp" 33 34 #include "tcuVector.hpp" 35 36 #include "deStringUtil.hpp" 37 38 #include <algorithm> // sort 39 #include <iterator> // distance 40 41 namespace vkt 42 { 43 namespace tessellation 44 { 45 46 class Buffer 47 { 48 public: 49 Buffer (const vk::DeviceInterface& vk, 50 const vk::VkDevice device, 51 vk::Allocator& allocator, 52 const vk::VkBufferCreateInfo& bufferCreateInfo, 53 const vk::MemoryRequirement memoryRequirement) 54 55 : m_buffer (createBuffer(vk, device, &bufferCreateInfo)) 56 , m_allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement)) 57 { 58 VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset())); 59 } 60 61 const vk::VkBuffer& get (void) const { return *m_buffer; } 62 const vk::VkBuffer& operator* (void) const { return get(); } 63 vk::Allocation& getAllocation (void) const { return *m_allocation; } 64 65 private: 66 const vk::Unique<vk::VkBuffer> m_buffer; 67 const de::UniquePtr<vk::Allocation> m_allocation; 68 69 // "deleted" 70 Buffer (const Buffer&); 71 Buffer& operator= (const Buffer&); 72 }; 73 74 class Image 75 { 76 public: 77 Image (const vk::DeviceInterface& vk, 78 const vk::VkDevice device, 79 vk::Allocator& allocator, 80 const vk::VkImageCreateInfo& imageCreateInfo, 81 const vk::MemoryRequirement memoryRequirement) 82 83 : m_image (createImage(vk, device, &imageCreateInfo)) 84 , m_allocation (allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement)) 85 { 86 VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset())); 87 } 88 89 const vk::VkImage& get (void) const { return *m_image; } 90 const vk::VkImage& operator* (void) const { return get(); } 91 vk::Allocation& getAllocation (void) const { return *m_allocation; } 92 93 private: 94 const vk::Unique<vk::VkImage> m_image; 95 const de::UniquePtr<vk::Allocation> m_allocation; 96 97 // "deleted" 98 Image (const Image&); 99 Image& operator= (const Image&); 100 }; 101 102 class GraphicsPipelineBuilder 103 { 104 public: 105 GraphicsPipelineBuilder (void) : m_renderSize (0, 0) 106 , m_shaderStageFlags (0u) 107 , m_cullModeFlags (vk::VK_CULL_MODE_NONE) 108 , m_frontFace (vk::VK_FRONT_FACE_COUNTER_CLOCKWISE) 109 , m_patchControlPoints (1u) 110 , m_blendEnable (false) 111 , m_primitiveTopology (vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) {} 112 113 GraphicsPipelineBuilder& setRenderSize (const tcu::IVec2& size) { m_renderSize = size; return *this; } 114 GraphicsPipelineBuilder& setShader (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkShaderStageFlagBits stage, const vk::ProgramBinary& binary, const vk::VkSpecializationInfo* specInfo); 115 GraphicsPipelineBuilder& setPatchControlPoints (const deUint32 controlPoints) { m_patchControlPoints = controlPoints; return *this; } 116 GraphicsPipelineBuilder& setCullModeFlags (const vk::VkCullModeFlags cullModeFlags) { m_cullModeFlags = cullModeFlags; return *this; } 117 GraphicsPipelineBuilder& setFrontFace (const vk::VkFrontFace frontFace) { m_frontFace = frontFace; return *this; } 118 GraphicsPipelineBuilder& setBlend (const bool enable) { m_blendEnable = enable; return *this; } 119 120 //! Applies only to pipelines without tessellation shaders. 121 GraphicsPipelineBuilder& setPrimitiveTopology (const vk::VkPrimitiveTopology topology) { m_primitiveTopology = topology; return *this; } 122 123 GraphicsPipelineBuilder& addVertexBinding (const vk::VkVertexInputBindingDescription vertexBinding) { m_vertexInputBindings.push_back(vertexBinding); return *this; } 124 GraphicsPipelineBuilder& addVertexAttribute (const vk::VkVertexInputAttributeDescription vertexAttribute) { m_vertexInputAttributes.push_back(vertexAttribute); return *this; } 125 126 //! Basic vertex input configuration (uses biding 0, location 0, etc.) 127 GraphicsPipelineBuilder& setVertexInputSingleAttribute (const vk::VkFormat vertexFormat, const deUint32 stride); 128 129 vk::Move<vk::VkPipeline> build (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkRenderPass renderPass); 130 131 private: 132 tcu::IVec2 m_renderSize; 133 vk::Move<vk::VkShaderModule> m_vertexShaderModule; 134 vk::Move<vk::VkShaderModule> m_fragmentShaderModule; 135 vk::Move<vk::VkShaderModule> m_geometryShaderModule; 136 vk::Move<vk::VkShaderModule> m_tessControlShaderModule; 137 vk::Move<vk::VkShaderModule> m_tessEvaluationShaderModule; 138 std::vector<vk::VkPipelineShaderStageCreateInfo> m_shaderStages; 139 std::vector<vk::VkVertexInputBindingDescription> m_vertexInputBindings; 140 std::vector<vk::VkVertexInputAttributeDescription> m_vertexInputAttributes; 141 vk::VkShaderStageFlags m_shaderStageFlags; 142 vk::VkCullModeFlags m_cullModeFlags; 143 vk::VkFrontFace m_frontFace; 144 deUint32 m_patchControlPoints; 145 bool m_blendEnable; 146 vk::VkPrimitiveTopology m_primitiveTopology; 147 148 GraphicsPipelineBuilder (const GraphicsPipelineBuilder&); // "deleted" 149 GraphicsPipelineBuilder& operator= (const GraphicsPipelineBuilder&); 150 }; 151 152 struct TessLevels 153 { 154 float inner[2]; 155 float outer[4]; 156 }; 157 158 enum TessPrimitiveType 159 { 160 TESSPRIMITIVETYPE_TRIANGLES = 0, 161 TESSPRIMITIVETYPE_QUADS, 162 TESSPRIMITIVETYPE_ISOLINES, 163 164 TESSPRIMITIVETYPE_LAST, 165 }; 166 167 enum SpacingMode 168 { 169 SPACINGMODE_EQUAL = 0, 170 SPACINGMODE_FRACTIONAL_ODD, 171 SPACINGMODE_FRACTIONAL_EVEN, 172 173 SPACINGMODE_LAST, 174 }; 175 176 enum Winding 177 { 178 WINDING_CCW = 0, 179 WINDING_CW, 180 181 WINDING_LAST, 182 }; 183 184 enum FeatureFlagBits 185 { 186 FEATURE_TESSELLATION_SHADER = 1u << 0, 187 FEATURE_GEOMETRY_SHADER = 1u << 1, 188 FEATURE_SHADER_FLOAT_64 = 1u << 2, 189 FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS = 1u << 3, 190 FEATURE_FRAGMENT_STORES_AND_ATOMICS = 1u << 4, 191 FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE = 1u << 5, 192 }; 193 typedef deUint32 FeatureFlags; 194 195 vk::VkBufferCreateInfo makeBufferCreateInfo (const vk::VkDeviceSize bufferSize, const vk::VkBufferUsageFlags usage); 196 vk::VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const vk::VkFormat format, const vk::VkImageUsageFlags usage, const deUint32 numArrayLayers); 197 vk::Move<vk::VkCommandPool> makeCommandPool (const vk::DeviceInterface& vk, const vk::VkDevice device, const deUint32 queueFamilyIndex); 198 vk::Move<vk::VkCommandBuffer> makeCommandBuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkCommandPool commandPool); 199 vk::Move<vk::VkDescriptorSet> makeDescriptorSet (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorPool descriptorPool, const vk::VkDescriptorSetLayout setLayout); 200 vk::Move<vk::VkPipelineLayout> makePipelineLayout (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorSetLayout descriptorSetLayout); 201 vk::Move<vk::VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const vk::DeviceInterface& vk, const vk::VkDevice device); 202 vk::Move<vk::VkPipeline> makeComputePipeline (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkShaderModule shaderModule, const vk::VkSpecializationInfo* specInfo); 203 vk::Move<vk::VkRenderPass> makeRenderPass (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkFormat colorFormat); 204 vk::Move<vk::VkRenderPass> makeRenderPassWithoutAttachments (const vk::DeviceInterface& vk, const vk::VkDevice device); 205 vk::Move<vk::VkFramebuffer> makeFramebuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkRenderPass renderPass, const vk::VkImageView colorAttachment, const deUint32 width, const deUint32 height, const deUint32 layers); 206 vk::Move<vk::VkFramebuffer> makeFramebufferWithoutAttachments (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkRenderPass renderPass); 207 vk::Move<vk::VkImageView> makeImageView (const vk::DeviceInterface& vk, const vk::VkDevice vkDevice, const vk::VkImage image, const vk::VkImageViewType viewType, const vk::VkFormat format, const vk::VkImageSubresourceRange subresourceRange); 208 vk::VkBufferImageCopy makeBufferImageCopy (const vk::VkExtent3D extent, const vk::VkImageSubresourceLayers subresourceLayers); 209 vk::VkBufferMemoryBarrier makeBufferMemoryBarrier (const vk::VkAccessFlags srcAccessMask, const vk::VkAccessFlags dstAccessMask, const vk::VkBuffer buffer, const vk::VkDeviceSize offset, const vk::VkDeviceSize bufferSizeBytes); 210 vk::VkImageMemoryBarrier makeImageMemoryBarrier (const vk::VkAccessFlags srcAccessMask, const vk::VkAccessFlags dstAccessMask, const vk::VkImageLayout oldLayout, const vk::VkImageLayout newLayout, const vk::VkImage image, const vk::VkImageSubresourceRange subresourceRange); 211 212 void beginCommandBuffer (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer); 213 void endCommandBuffer (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer); 214 void submitCommandsAndWait (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkQueue queue, const vk::VkCommandBuffer commandBuffer); 215 void beginRenderPass (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer, const vk::VkRenderPass renderPass, const vk::VkFramebuffer framebuffer, const vk::VkRect2D& renderArea, const tcu::Vec4& clearColor); 216 void beginRenderPassWithRasterizationDisabled (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer, const vk::VkRenderPass renderPass, const vk::VkFramebuffer framebuffer); 217 void endRenderPass (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer); 218 void requireFeatures (const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const FeatureFlags flags); 219 220 float getClampedTessLevel (const SpacingMode mode, const float tessLevel); 221 int getRoundedTessLevel (const SpacingMode mode, const float clampedTessLevel); 222 int getClampedRoundedTessLevel (const SpacingMode mode, const float tessLevel); 223 void getClampedRoundedTriangleTessLevels (const SpacingMode mode, const float* innerSrc, const float* outerSrc, int* innerDst, int* outerDst); 224 void getClampedRoundedQuadTessLevels (const SpacingMode mode, const float* innerSrc, const float* outerSrc, int* innerDst, int* outerDst); 225 void getClampedRoundedIsolineTessLevels (const SpacingMode mode, const float* outerSrc, int* outerDst); 226 int numOuterTessellationLevels (const TessPrimitiveType primitiveType); 227 std::string getTessellationLevelsString (const TessLevels& tessLevels, const TessPrimitiveType primitiveType); 228 std::string getTessellationLevelsString (const float* inner, const float* outer); 229 bool isPatchDiscarded (const TessPrimitiveType primitiveType, const float* outerLevels); 230 std::vector<tcu::Vec3> generateReferenceTriangleTessCoords (const SpacingMode spacingMode, const int inner, const int outer0, const int outer1, const int outer2); 231 std::vector<tcu::Vec3> generateReferenceQuadTessCoords (const SpacingMode spacingMode, const int inner0, const int inner1, const int outer0, const int outer1, const int outer2, const int outer3); 232 std::vector<tcu::Vec3> generateReferenceIsolineTessCoords (const int outer0, const int outer1); 233 int referenceVertexCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels); 234 int referencePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels); 235 int numVerticesPerPrimitive (const TessPrimitiveType primitiveType, const bool usePointMode); 236 237 static inline const char* getTessPrimitiveTypeShaderName (const TessPrimitiveType type) 238 { 239 switch (type) 240 { 241 case TESSPRIMITIVETYPE_TRIANGLES: return "triangles"; 242 case TESSPRIMITIVETYPE_QUADS: return "quads"; 243 case TESSPRIMITIVETYPE_ISOLINES: return "isolines"; 244 default: 245 DE_ASSERT(false); 246 return DE_NULL; 247 } 248 } 249 250 static inline const char* getSpacingModeShaderName (SpacingMode mode) 251 { 252 switch (mode) 253 { 254 case SPACINGMODE_EQUAL: return "equal_spacing"; 255 case SPACINGMODE_FRACTIONAL_ODD: return "fractional_odd_spacing"; 256 case SPACINGMODE_FRACTIONAL_EVEN: return "fractional_even_spacing"; 257 default: 258 DE_ASSERT(false); 259 return DE_NULL; 260 } 261 } 262 263 static inline const char* getWindingShaderName (const Winding winding) 264 { 265 switch (winding) 266 { 267 case WINDING_CCW: return "ccw"; 268 case WINDING_CW: return "cw"; 269 default: 270 DE_ASSERT(false); 271 return DE_NULL; 272 } 273 } 274 275 static inline const char* getGeometryShaderInputPrimitiveTypeShaderName (const TessPrimitiveType type, const bool usePointMode) 276 { 277 if (usePointMode) 278 return "points"; 279 280 switch (type) 281 { 282 case TESSPRIMITIVETYPE_TRIANGLES: 283 case TESSPRIMITIVETYPE_QUADS: 284 return "triangles"; 285 286 case TESSPRIMITIVETYPE_ISOLINES: 287 return "lines"; 288 289 default: 290 DE_ASSERT(false); 291 return DE_NULL; 292 } 293 } 294 295 static inline const char* getGeometryShaderOutputPrimitiveTypeShaderName (const TessPrimitiveType type, const bool usePointMode) 296 { 297 if (usePointMode) 298 return "points"; 299 300 switch (type) 301 { 302 case TESSPRIMITIVETYPE_TRIANGLES: 303 case TESSPRIMITIVETYPE_QUADS: 304 return "triangle_strip"; 305 306 case TESSPRIMITIVETYPE_ISOLINES: 307 return "line_strip"; 308 309 default: 310 DE_ASSERT(false); 311 return DE_NULL; 312 } 313 } 314 315 template<typename T> 316 inline std::size_t sizeInBytes (const std::vector<T>& vec) 317 { 318 return vec.size() * sizeof(vec[0]); 319 } 320 321 template <typename T> 322 static std::vector<T> sorted (const std::vector<T>& unsorted) 323 { 324 std::vector<T> result = unsorted; 325 std::sort(result.begin(), result.end()); 326 return result; 327 } 328 329 template <typename T, typename P> 330 static std::vector<T> sorted (const std::vector<T>& unsorted, P pred) 331 { 332 std::vector<T> result = unsorted; 333 std::sort(result.begin(), result.end(), pred); 334 return result; 335 } 336 337 template <typename IterT> 338 std::string elemsStr (const IterT& begin, const IterT& end, int wrapLengthParam = 0, int numIndentationSpaces = 0) 339 { 340 const int bigInt = ~0u/2; 341 const std::string baseIndentation = std::string(numIndentationSpaces, ' '); 342 const std::string deepIndentation = baseIndentation + std::string(4, ' '); 343 const int wrapLength = wrapLengthParam > 0 ? wrapLengthParam : bigInt; 344 const int length = static_cast<int>(std::distance(begin, end)); 345 std::string result; 346 347 if (length > wrapLength) 348 result += "(amount: " + de::toString(length) + ") "; 349 result += std::string() + "{" + (length > wrapLength ? "\n"+deepIndentation : " "); 350 351 { 352 int index = 0; 353 for (IterT it = begin; it != end; ++it) 354 { 355 if (it != begin) 356 result += std::string() + ", " + (index % wrapLength == 0 ? "\n"+deepIndentation : ""); 357 result += de::toString(*it); 358 index++; 359 } 360 361 result += length > wrapLength ? "\n"+baseIndentation : " "; 362 } 363 364 result += "}"; 365 return result; 366 } 367 368 template <typename ContainerT> 369 std::string containerStr (const ContainerT& c, int wrapLengthParam = 0, int numIndentationSpaces = 0) 370 { 371 return elemsStr(c.begin(), c.end(), wrapLengthParam, numIndentationSpaces); 372 } 373 374 //! Copy 'count' objects of type T from 'memory' into a vector. 375 //! 'offset' is the offset of first object in memory, and 'stride' is the distance between consecutive objects. 376 template<typename T> 377 std::vector<T> readInterleavedData (const int count, const void* memory, const int offset, const int stride) 378 { 379 std::vector<T> results(count); 380 const deUint8* pData = static_cast<const deUint8*>(memory) + offset; 381 382 for (int i = 0; i < count; ++i) 383 { 384 deMemcpy(&results[i], pData, sizeof(T)); 385 pData += stride; 386 } 387 388 return results; 389 } 390 391 } // tessellation 392 } // vkt 393 394 #endif // _VKTTESSELLATIONUTIL_HPP 395