1 /* 2 * Copyright (c) 2015-2017 The Khronos Group Inc. 3 * Copyright (c) 2015-2017 Valve Corporation 4 * Copyright (c) 2015-2017 LunarG, Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 19 * Author: Dave Houlton <daveh (at) lunarg.com> 20 */ 21 22 #ifndef VKRENDERFRAMEWORK_H 23 #define VKRENDERFRAMEWORK_H 24 25 #ifdef ANDROID 26 #include "vktestframeworkandroid.h" 27 class VkImageObj; 28 #else 29 #include "vktestframework.h" 30 #endif 31 32 #include <algorithm> 33 #include <array> 34 #include <map> 35 #include <vector> 36 37 using namespace std; 38 39 using vk_testing::MakeVkHandles; 40 41 template <class Dst, class Src> 42 std::vector<Dst *> MakeTestbindingHandles(const std::vector<Src *> &v) { 43 std::vector<Dst *> handles; 44 handles.reserve(v.size()); 45 std::transform(v.begin(), v.end(), std::back_inserter(handles), [](const Src *o) { return static_cast<Dst *>(o); }); 46 return handles; 47 } 48 49 class VkDeviceObj : public vk_testing::Device { 50 public: 51 VkDeviceObj(uint32_t id, VkPhysicalDevice obj); 52 VkDeviceObj(uint32_t id, VkPhysicalDevice obj, std::vector<const char *> &extension_names, 53 VkPhysicalDeviceFeatures *features = nullptr); 54 55 uint32_t QueueFamilyMatching(VkQueueFlags with, VkQueueFlags without, bool all_bits = true); 56 uint32_t QueueFamilyWithoutCapabilities(VkQueueFlags capabilities) { 57 // an all_bits match with 0 matches all 58 return QueueFamilyMatching(VkQueueFlags(0), capabilities, true /* all_bits with */); 59 } 60 61 VkDevice device() { return handle(); } 62 void get_device_queue(); 63 64 uint32_t id; 65 VkPhysicalDeviceProperties props; 66 std::vector<VkQueueFamilyProperties> queue_props; 67 68 VkQueue m_queue; 69 }; 70 71 class VkCommandPoolObj; 72 class VkCommandBufferObj; 73 class VkDepthStencilObj; 74 75 class VkRenderFramework : public VkTestFramework { 76 public: 77 VkRenderFramework(); 78 ~VkRenderFramework(); 79 80 VkInstance instance() { return inst; } 81 VkDevice device() { return m_device->device(); } 82 VkDeviceObj *DeviceObj() const { return m_device; } 83 VkPhysicalDevice gpu(); 84 VkRenderPass renderPass() { return m_renderPass; } 85 const VkRenderPassCreateInfo &RenderPassInfo() const { return renderPass_info_; }; 86 VkFramebuffer framebuffer() { return m_framebuffer; } 87 void InitViewport(float width, float height); 88 void InitViewport(); 89 void InitRenderTarget(); 90 void InitRenderTarget(uint32_t targets); 91 void InitRenderTarget(VkImageView *dsBinding); 92 void InitRenderTarget(uint32_t targets, VkImageView *dsBinding); 93 void InitFramework(PFN_vkDebugReportCallbackEXT = NULL, void *userData = NULL); 94 95 void ShutdownFramework(); 96 void GetPhysicalDeviceFeatures(VkPhysicalDeviceFeatures *features); 97 void InitState(VkPhysicalDeviceFeatures *features = nullptr, const VkCommandPoolCreateFlags flags = 0); 98 99 const VkRenderPassBeginInfo &renderPassBeginInfo() const { return m_renderPassBeginInfo; } 100 101 bool InstanceLayerSupported(const char *name, uint32_t specVersion = 0, uint32_t implementationVersion = 0); 102 bool EnableDeviceProfileLayer(); 103 bool InstanceExtensionSupported(const char *name, uint32_t specVersion = 0); 104 bool DeviceExtensionSupported(VkPhysicalDevice dev, const char *layer, const char *name, uint32_t specVersion = 0); 105 106 protected: 107 VkApplicationInfo app_info; 108 VkInstance inst; 109 VkPhysicalDevice objs[16]; 110 uint32_t gpu_count; 111 VkDeviceObj *m_device; 112 VkCommandPoolObj *m_commandPool; 113 VkCommandBufferObj *m_commandBuffer; 114 VkRenderPass m_renderPass; 115 VkRenderPassCreateInfo renderPass_info_ = {}; 116 VkFramebuffer m_framebuffer; 117 std::vector<VkViewport> m_viewports; 118 std::vector<VkRect2D> m_scissors; 119 float m_lineWidth; 120 float m_depthBiasConstantFactor; 121 float m_depthBiasClamp; 122 float m_depthBiasSlopeFactor; 123 float m_blendConstants[4]; 124 float m_minDepthBounds; 125 float m_maxDepthBounds; 126 uint32_t m_compareMask; 127 uint32_t m_writeMask; 128 uint32_t m_reference; 129 bool m_addRenderPassSelfDependency; 130 std::vector<VkClearValue> m_renderPassClearValues; 131 VkRenderPassBeginInfo m_renderPassBeginInfo; 132 vector<VkImageObj *> m_renderTargets; 133 float m_width, m_height; 134 VkFormat m_render_target_fmt; 135 VkFormat m_depth_stencil_fmt; 136 VkClearColorValue m_clear_color; 137 bool m_clear_via_load_op; 138 float m_depth_clear_color; 139 uint32_t m_stencil_clear_color; 140 VkDepthStencilObj *m_depthStencil; 141 PFN_vkCreateDebugReportCallbackEXT m_CreateDebugReportCallback; 142 PFN_vkDestroyDebugReportCallbackEXT m_DestroyDebugReportCallback; 143 PFN_vkDebugReportMessageEXT m_DebugReportMessage; 144 VkDebugReportCallbackEXT m_globalMsgCallback; 145 VkDebugReportCallbackEXT m_devMsgCallback; 146 147 std::vector<const char *> m_instance_layer_names; 148 std::vector<const char *> m_instance_extension_names; 149 std::vector<const char *> m_device_extension_names; 150 151 /* 152 * SetUp and TearDown are called by the Google Test framework 153 * to initialize a test framework based on this class. 154 */ 155 virtual void SetUp() { 156 this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 157 this->app_info.pNext = NULL; 158 this->app_info.pApplicationName = "base"; 159 this->app_info.applicationVersion = 1; 160 this->app_info.pEngineName = "unittest"; 161 this->app_info.engineVersion = 1; 162 this->app_info.apiVersion = VK_API_VERSION_1_0; 163 164 InitFramework(); 165 } 166 167 virtual void TearDown() { ShutdownFramework(); } 168 }; 169 170 class VkDescriptorSetObj; 171 class VkConstantBufferObj; 172 class VkPipelineObj; 173 class VkDescriptorSetObj; 174 175 class VkCommandPoolObj : public vk_testing::CommandPool { 176 public: 177 VkCommandPoolObj(VkDeviceObj *device, uint32_t queue_family_index, VkCommandPoolCreateFlags flags = 0); 178 }; 179 180 class VkCommandBufferObj : public vk_testing::CommandBuffer { 181 public: 182 VkCommandBufferObj(VkDeviceObj *device, VkCommandPoolObj *pool, VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY); 183 void PipelineBarrier(VkPipelineStageFlags src_stages, VkPipelineStageFlags dest_stages, VkDependencyFlags dependencyFlags, 184 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, 185 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, 186 const VkImageMemoryBarrier *pImageMemoryBarriers); 187 void ClearAllBuffers(const vector<VkImageObj *> &color_objs, VkClearColorValue clear_color, 188 VkDepthStencilObj *depth_stencil_obj, float depth_clear_value, uint32_t stencil_clear_value); 189 void PrepareAttachments(const vector<VkImageObj *> &color_atts, VkDepthStencilObj *depth_stencil_att); 190 void BindDescriptorSet(VkDescriptorSetObj &descriptorSet); 191 void BindVertexBuffer(VkConstantBufferObj *vertexBuffer, VkDeviceSize offset, uint32_t binding); 192 void BeginRenderPass(const VkRenderPassBeginInfo &info); 193 void EndRenderPass(); 194 void FillBuffer(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize fill_size, uint32_t data); 195 void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); 196 void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, 197 uint32_t firstInstance); 198 void QueueCommandBuffer(bool checkSuccess = true); 199 void QueueCommandBuffer(VkFence fence, bool checkSuccess = true); 200 void SetViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports); 201 void SetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference); 202 void UpdateBuffer(VkBuffer buffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData); 203 void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, 204 uint32_t regionCount, const VkImageCopy *pRegions); 205 void ResolveImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, 206 uint32_t regionCount, const VkImageResolve *pRegions); 207 void ClearColorImage(VkImage image, VkImageLayout imageLayout, const VkClearColorValue *pColor, uint32_t rangeCount, 208 const VkImageSubresourceRange *pRanges); 209 void ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue *pColor, 210 uint32_t rangeCount, const VkImageSubresourceRange *pRanges); 211 212 protected: 213 VkDeviceObj *m_device; 214 }; 215 216 class VkConstantBufferObj : public vk_testing::Buffer { 217 public: 218 VkConstantBufferObj(VkDeviceObj *device, 219 VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); 220 VkConstantBufferObj(VkDeviceObj *device, VkDeviceSize size, const void *data, 221 VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); 222 223 VkDescriptorBufferInfo m_descriptorBufferInfo; 224 225 protected: 226 VkDeviceObj *m_device; 227 }; 228 229 class VkRenderpassObj { 230 public: 231 VkRenderpassObj(VkDeviceObj *device); 232 ~VkRenderpassObj(); 233 VkRenderPass handle() { return m_renderpass; } 234 235 protected: 236 VkRenderPass m_renderpass; 237 VkDevice device; 238 }; 239 240 class VkImageObj : public vk_testing::Image { 241 public: 242 VkImageObj(VkDeviceObj *dev); 243 bool IsCompatible(VkImageUsageFlags usages, VkFormatFeatureFlags features); 244 245 public: 246 void Init(uint32_t const width, uint32_t const height, uint32_t const mipLevels, VkFormat const format, VkFlags const usage, 247 VkImageTiling const tiling = VK_IMAGE_TILING_LINEAR, VkMemoryPropertyFlags const reqs = 0, 248 const std::vector<uint32_t> *queue_families = nullptr); 249 250 void init(const VkImageCreateInfo *create_info); 251 252 void InitNoLayout(uint32_t const width, uint32_t const height, uint32_t const mipLevels, VkFormat const format, 253 VkFlags const usage, VkImageTiling tiling = VK_IMAGE_TILING_LINEAR, VkMemoryPropertyFlags reqs = 0, 254 const std::vector<uint32_t> *queue_families = nullptr); 255 256 // void clear( CommandBuffer*, uint32_t[4] ); 257 258 void Layout(VkImageLayout const layout) { m_descriptorImageInfo.imageLayout = layout; } 259 260 VkDeviceMemory memory() const { return Image::memory().handle(); } 261 262 void *MapMemory() { return Image::memory().map(); } 263 264 void UnmapMemory() { Image::memory().unmap(); } 265 266 void ImageMemoryBarrier(VkCommandBufferObj *cmd, VkImageAspectFlags aspect, VkFlags output_mask, VkFlags input_mask, 267 VkImageLayout image_layout); 268 269 VkResult CopyImage(VkImageObj &src_image); 270 271 VkImage image() const { return handle(); } 272 273 VkImageView targetView(VkFormat format) { 274 if (!m_targetView.initialized()) { 275 VkImageViewCreateInfo createView = {}; 276 createView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 277 createView.image = handle(); 278 createView.viewType = VK_IMAGE_VIEW_TYPE_2D; 279 createView.format = format; 280 createView.components.r = VK_COMPONENT_SWIZZLE_R; 281 createView.components.g = VK_COMPONENT_SWIZZLE_G; 282 createView.components.b = VK_COMPONENT_SWIZZLE_B; 283 createView.components.a = VK_COMPONENT_SWIZZLE_A; 284 createView.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 285 createView.flags = 0; 286 m_targetView.init(*m_device, createView); 287 } 288 return m_targetView.handle(); 289 } 290 291 void SetLayout(VkCommandBufferObj *cmd_buf, VkImageAspectFlags aspect, VkImageLayout image_layout); 292 void SetLayout(VkImageAspectFlags aspect, VkImageLayout image_layout); 293 294 VkImageLayout Layout() const { return m_descriptorImageInfo.imageLayout; } 295 uint32_t width() const { return extent().width; } 296 uint32_t height() const { return extent().height; } 297 VkDeviceObj *device() const { return m_device; } 298 299 protected: 300 VkDeviceObj *m_device; 301 302 vk_testing::ImageView m_targetView; 303 VkDescriptorImageInfo m_descriptorImageInfo; 304 }; 305 306 class VkTextureObj : public VkImageObj { 307 public: 308 VkTextureObj(VkDeviceObj *device, uint32_t *colors = NULL); 309 310 VkDescriptorImageInfo m_imageInfo; 311 312 protected: 313 VkDeviceObj *m_device; 314 vk_testing::ImageView m_textureView; 315 }; 316 317 class VkDepthStencilObj : public VkImageObj { 318 public: 319 VkDepthStencilObj(VkDeviceObj *device); 320 void Init(VkDeviceObj *device, int32_t width, int32_t height, VkFormat format, 321 VkImageUsageFlags usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); 322 bool Initialized(); 323 VkImageView *BindInfo(); 324 325 VkFormat Format() const; 326 327 protected: 328 VkDeviceObj *m_device; 329 bool m_initialized; 330 vk_testing::ImageView m_imageView; 331 VkFormat m_depth_stencil_fmt; 332 VkImageView m_attachmentBindInfo; 333 }; 334 335 class VkSamplerObj : public vk_testing::Sampler { 336 public: 337 VkSamplerObj(VkDeviceObj *device); 338 339 protected: 340 VkDeviceObj *m_device; 341 }; 342 343 class VkDescriptorSetLayoutObj : public vk_testing::DescriptorSetLayout { 344 public: 345 VkDescriptorSetLayoutObj() = default; 346 VkDescriptorSetLayoutObj(const VkDeviceObj *device, 347 const std::vector<VkDescriptorSetLayoutBinding> &descriptor_set_bindings = {}, 348 VkDescriptorSetLayoutCreateFlags flags = 0); 349 350 // Move constructor and move assignment operator for Visual Studio 2013 351 VkDescriptorSetLayoutObj(VkDescriptorSetLayoutObj &&src) : DescriptorSetLayout(std::move(src)){}; 352 VkDescriptorSetLayoutObj &operator=(VkDescriptorSetLayoutObj &&src) { 353 DescriptorSetLayout::operator=(std::move(src)); 354 return *this; 355 } 356 }; 357 358 class VkDescriptorSetObj : public vk_testing::DescriptorPool { 359 public: 360 VkDescriptorSetObj(VkDeviceObj *device); 361 ~VkDescriptorSetObj(); 362 363 int AppendDummy(); 364 int AppendBuffer(VkDescriptorType type, VkConstantBufferObj &constantBuffer); 365 int AppendSamplerTexture(VkSamplerObj *sampler, VkTextureObj *texture); 366 void CreateVKDescriptorSet(VkCommandBufferObj *commandBuffer); 367 368 VkDescriptorSet GetDescriptorSetHandle() const; 369 VkPipelineLayout GetPipelineLayout() const; 370 371 protected: 372 VkDeviceObj *m_device; 373 std::vector<VkDescriptorSetLayoutBinding> m_layout_bindings; 374 std::map<VkDescriptorType, int> m_type_counts; 375 int m_nextSlot; 376 377 vector<VkDescriptorImageInfo> m_imageSamplerDescriptors; 378 vector<VkWriteDescriptorSet> m_writes; 379 380 vk_testing::DescriptorSetLayout m_layout; 381 vk_testing::PipelineLayout m_pipeline_layout; 382 vk_testing::DescriptorSet *m_set = NULL; 383 }; 384 385 class VkShaderObj : public vk_testing::ShaderModule { 386 public: 387 VkShaderObj(VkDeviceObj *device, const char *shaderText, VkShaderStageFlagBits stage, VkRenderFramework *framework, 388 char const *name = "main"); 389 VkPipelineShaderStageCreateInfo const &GetStageCreateInfo() const; 390 391 protected: 392 VkPipelineShaderStageCreateInfo m_stage_info; 393 VkDeviceObj *m_device; 394 }; 395 396 class VkPipelineLayoutObj : public vk_testing::PipelineLayout { 397 public: 398 VkPipelineLayoutObj() = default; 399 VkPipelineLayoutObj(VkDeviceObj *device, const std::vector<const VkDescriptorSetLayoutObj *> &descriptor_layouts = {}, 400 const std::vector<VkPushConstantRange> &push_constant_ranges = {}); 401 402 // Move constructor and move assignment operator for Visual Studio 2013 403 VkPipelineLayoutObj(VkPipelineLayoutObj &&src) : PipelineLayout(std::move(src)) {} 404 VkPipelineLayoutObj &operator=(VkPipelineLayoutObj &&src) { 405 PipelineLayout::operator=(std::move(src)); 406 return *this; 407 } 408 409 void Reset(); 410 }; 411 412 class VkPipelineObj : public vk_testing::Pipeline { 413 public: 414 VkPipelineObj(VkDeviceObj *device); 415 void AddShader(VkShaderObj *shaderObj); 416 void AddShader(VkPipelineShaderStageCreateInfo const &createInfo); 417 void AddVertexInputAttribs(VkVertexInputAttributeDescription *vi_attrib, uint32_t count); 418 void AddVertexInputBindings(VkVertexInputBindingDescription *vi_binding, uint32_t count); 419 void AddColorAttachment(uint32_t binding, const VkPipelineColorBlendAttachmentState &att); 420 void MakeDynamic(VkDynamicState state); 421 422 void AddDefaultColorAttachment(VkColorComponentFlags writeMask = 0xf /*=R|G|B|A*/) { 423 VkPipelineColorBlendAttachmentState att = {}; 424 att.blendEnable = VK_FALSE; 425 att.colorWriteMask = writeMask; 426 AddColorAttachment(0, att); 427 } 428 429 void SetDepthStencil(const VkPipelineDepthStencilStateCreateInfo *); 430 void SetMSAA(const VkPipelineMultisampleStateCreateInfo *ms_state); 431 void SetInputAssembly(const VkPipelineInputAssemblyStateCreateInfo *ia_state); 432 void SetRasterization(const VkPipelineRasterizationStateCreateInfo *rs_state); 433 void SetTessellation(const VkPipelineTessellationStateCreateInfo *te_state); 434 void SetViewport(const vector<VkViewport> viewports); 435 void SetScissor(const vector<VkRect2D> scissors); 436 437 void InitGraphicsPipelineCreateInfo(VkGraphicsPipelineCreateInfo *gp_ci); 438 439 VkResult CreateVKPipeline(VkPipelineLayout layout, VkRenderPass render_pass, VkGraphicsPipelineCreateInfo *gp_ci = nullptr); 440 441 protected: 442 VkPipelineVertexInputStateCreateInfo m_vi_state; 443 VkPipelineInputAssemblyStateCreateInfo m_ia_state; 444 VkPipelineRasterizationStateCreateInfo m_rs_state; 445 VkPipelineColorBlendStateCreateInfo m_cb_state; 446 VkPipelineDepthStencilStateCreateInfo const *m_ds_state; 447 VkPipelineViewportStateCreateInfo m_vp_state; 448 VkPipelineMultisampleStateCreateInfo m_ms_state; 449 VkPipelineTessellationStateCreateInfo const *m_te_state; 450 VkPipelineDynamicStateCreateInfo m_pd_state; 451 vector<VkDynamicState> m_dynamic_state_enables; 452 vector<VkViewport> m_viewports; 453 vector<VkRect2D> m_scissors; 454 VkDeviceObj *m_device; 455 vector<VkPipelineShaderStageCreateInfo> m_shaderStages; 456 vector<VkPipelineColorBlendAttachmentState> m_colorAttachments; 457 }; 458 459 #endif // VKRENDERFRAMEWORK_H 460