1 /* 2 * Copyright (c) 2015-2016 The Khronos Group Inc. 3 * Copyright (c) 2015-2016 Valve Corporation 4 * Copyright (c) 2015-2016 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials are 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included in 14 * all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS. 24 * 25 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 26 */ 27 28 #ifndef VKRENDERFRAMEWORK_H 29 #define VKRENDERFRAMEWORK_H 30 31 #ifdef ANDROID 32 #include "vktestframeworkandroid.h" 33 class VkImageObj; 34 #else 35 #include "vktestframework.h" 36 #endif 37 38 #include <vector> 39 40 using namespace std; 41 42 class VkDeviceObj : public vk_testing::Device { 43 public: 44 VkDeviceObj(uint32_t id, VkPhysicalDevice obj); 45 VkDeviceObj(uint32_t id, VkPhysicalDevice obj, 46 std::vector<const char *> &layers, 47 std::vector<const char *> &extension_names); 48 49 VkDevice device() { return handle(); } 50 void get_device_queue(); 51 52 uint32_t id; 53 VkPhysicalDeviceProperties props; 54 const VkQueueFamilyProperties *queue_props; 55 56 VkQueue m_queue; 57 }; 58 59 class VkDepthStencilObj : public vk_testing::Image { 60 public: 61 VkDepthStencilObj(); 62 void Init(VkDeviceObj *device, int32_t width, int32_t height, 63 VkFormat format); 64 bool Initialized(); 65 VkImageView *BindInfo(); 66 67 protected: 68 VkDeviceObj *m_device; 69 bool m_initialized; 70 vk_testing::ImageView m_imageView; 71 VkFormat m_depth_stencil_fmt; 72 VkImageView m_attachmentBindInfo; 73 }; 74 75 class VkCommandBufferObj; 76 77 class VkRenderFramework : public VkTestFramework { 78 public: 79 VkRenderFramework(); 80 ~VkRenderFramework(); 81 82 VkDevice device() { return m_device->device(); } 83 VkPhysicalDevice gpu() { return objs[0]; } 84 VkRenderPass renderPass() { return m_renderPass; } 85 VkFramebuffer framebuffer() { return m_framebuffer; } 86 void InitViewport(float width, float height); 87 void InitViewport(); 88 void InitRenderTarget(); 89 void InitRenderTarget(uint32_t targets); 90 void InitRenderTarget(VkImageView *dsBinding); 91 void InitRenderTarget(uint32_t targets, VkImageView *dsBinding); 92 void InitFramework(); 93 void InitFramework(std::vector<const char *> instance_layer_names, 94 std::vector<const char *> device_layer_names, 95 std::vector<const char *> instance_extension_names, 96 std::vector<const char *> device_extension_names, 97 PFN_vkDebugReportCallbackEXT = NULL, 98 void *userData = NULL); 99 100 void ShutdownFramework(); 101 void InitState(); 102 103 const VkRenderPassBeginInfo &renderPassBeginInfo() const { 104 return m_renderPassBeginInfo; 105 } 106 107 protected: 108 VkApplicationInfo app_info; 109 VkInstance inst; 110 VkPhysicalDevice objs[16]; 111 uint32_t gpu_count; 112 VkDeviceObj *m_device; 113 VkCommandPool m_commandPool; 114 VkCommandBufferObj *m_commandBuffer; 115 VkRenderPass m_renderPass; 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 std::vector<VkClearValue> m_renderPassClearValues; 130 VkRenderPassBeginInfo m_renderPassBeginInfo; 131 vector<VkImageObj *> m_renderTargets; 132 float m_width, m_height; 133 VkFormat m_render_target_fmt; 134 VkFormat m_depth_stencil_fmt; 135 VkClearColorValue m_clear_color; 136 bool m_clear_via_load_op; 137 float m_depth_clear_color; 138 uint32_t m_stencil_clear_color; 139 VkDepthStencilObj *m_depthStencil; 140 PFN_vkCreateDebugReportCallbackEXT m_CreateDebugReportCallback; 141 PFN_vkDestroyDebugReportCallbackEXT m_DestroyDebugReportCallback; 142 PFN_vkDebugReportMessageEXT m_DebugReportMessage; 143 VkDebugReportCallbackEXT m_globalMsgCallback; 144 VkDebugReportCallbackEXT m_devMsgCallback; 145 146 /* 147 * SetUp and TearDown are called by the Google Test framework 148 * to initialize a test framework based on this class. 149 */ 150 virtual void SetUp() { 151 this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 152 this->app_info.pNext = NULL; 153 this->app_info.pApplicationName = "base"; 154 this->app_info.applicationVersion = 1; 155 this->app_info.pEngineName = "unittest"; 156 this->app_info.engineVersion = 1; 157 this->app_info.apiVersion = VK_API_VERSION_1_0; 158 159 InitFramework(); 160 } 161 162 virtual void TearDown() { ShutdownFramework(); } 163 }; 164 165 class VkDescriptorSetObj; 166 class VkIndexBufferObj; 167 class VkConstantBufferObj; 168 class VkPipelineObj; 169 class VkDescriptorSetObj; 170 171 class VkCommandBufferObj : public vk_testing::CommandBuffer { 172 public: 173 VkCommandBufferObj(VkDeviceObj *device, VkCommandPool pool); 174 VkCommandBuffer GetBufferHandle(); 175 VkResult BeginCommandBuffer(); 176 VkResult BeginCommandBuffer(VkCommandBufferBeginInfo *pInfo); 177 VkResult EndCommandBuffer(); 178 void PipelineBarrier(VkPipelineStageFlags src_stages, 179 VkPipelineStageFlags dest_stages, 180 VkDependencyFlags dependencyFlags, 181 uint32_t memoryBarrierCount, 182 const VkMemoryBarrier *pMemoryBarriers, 183 uint32_t bufferMemoryBarrierCount, 184 const VkBufferMemoryBarrier *pBufferMemoryBarriers, 185 uint32_t imageMemoryBarrierCount, 186 const VkImageMemoryBarrier *pImageMemoryBarriers); 187 void AddRenderTarget(VkImageObj *renderTarget); 188 void AddDepthStencil(); 189 void ClearAllBuffers(VkClearColorValue clear_color, float depth_clear_color, 190 uint32_t stencil_clear_color, 191 VkDepthStencilObj *depthStencilObj); 192 void PrepareAttachments(); 193 void BindPipeline(VkPipelineObj &pipeline); 194 void BindDescriptorSet(VkDescriptorSetObj &descriptorSet); 195 void BindVertexBuffer(VkConstantBufferObj *vertexBuffer, 196 VkDeviceSize offset, uint32_t binding); 197 void BindIndexBuffer(VkIndexBufferObj *indexBuffer, VkDeviceSize offset); 198 void BeginRenderPass(const VkRenderPassBeginInfo &info); 199 void EndRenderPass(); 200 void FillBuffer(VkBuffer buffer, VkDeviceSize offset, 201 VkDeviceSize fill_size, uint32_t data); 202 void Draw(uint32_t vertexCount, uint32_t instanceCount, 203 uint32_t firstVertex, uint32_t firstInstance); 204 void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, 205 uint32_t firstIndex, int32_t vertexOffset, 206 uint32_t firstInstance); 207 void QueueCommandBuffer(); 208 void QueueCommandBuffer(VkFence fence); 209 void SetViewport(uint32_t firstViewport, uint32_t viewportCount, 210 const VkViewport *pViewports); 211 void SetScissor(uint32_t firstScissor, uint32_t scissorCount, 212 const VkRect2D *pScissors); 213 void SetLineWidth(float lineWidth); 214 void SetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, 215 float depthBiasSlopeFactor); 216 void SetBlendConstants(const float blendConstants[4]); 217 void SetDepthBounds(float minDepthBounds, float maxDepthBounds); 218 void SetStencilReadMask(VkStencilFaceFlags faceMask, uint32_t compareMask); 219 void SetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask); 220 void SetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference); 221 void UpdateBuffer(VkBuffer buffer, VkDeviceSize dstOffset, 222 VkDeviceSize dataSize, const uint32_t *pData); 223 void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, 224 VkImage dstImage, VkImageLayout dstImageLayout, 225 uint32_t regionCount, const VkImageCopy *pRegions); 226 void ResolveImage(VkImage srcImage, VkImageLayout srcImageLayout, 227 VkImage dstImage, VkImageLayout dstImageLayout, 228 uint32_t regionCount, const VkImageResolve *pRegions); 229 230 protected: 231 VkDeviceObj *m_device; 232 vector<VkImageObj *> m_renderTargets; 233 }; 234 235 class VkConstantBufferObj : public vk_testing::Buffer { 236 public: 237 VkConstantBufferObj(VkDeviceObj *device); 238 VkConstantBufferObj(VkDeviceObj *device, int constantCount, 239 int constantSize, const void *data); 240 ~VkConstantBufferObj(); 241 void BufferMemoryBarrier( 242 VkFlags srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | 243 VK_ACCESS_SHADER_WRITE_BIT | 244 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 245 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 246 VK_ACCESS_TRANSFER_WRITE_BIT, 247 VkFlags dstAccessMask = VK_ACCESS_HOST_READ_BIT | 248 VK_ACCESS_INDIRECT_COMMAND_READ_BIT | 249 VK_ACCESS_INDEX_READ_BIT | 250 VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | 251 VK_ACCESS_UNIFORM_READ_BIT | 252 VK_ACCESS_SHADER_READ_BIT | 253 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 254 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | 255 VK_ACCESS_MEMORY_READ_BIT); 256 257 void Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset, 258 uint32_t binding); 259 260 VkDescriptorBufferInfo m_descriptorBufferInfo; 261 262 protected: 263 VkDeviceObj *m_device; 264 vk_testing::BufferView m_bufferView; 265 int m_numVertices; 266 int m_stride; 267 vk_testing::CommandPool *m_commandPool; 268 VkCommandBufferObj *m_commandBuffer; 269 vk_testing::Fence m_fence; 270 }; 271 272 class VkIndexBufferObj : public VkConstantBufferObj { 273 public: 274 VkIndexBufferObj(VkDeviceObj *device); 275 void CreateAndInitBuffer(int numIndexes, VkIndexType dataFormat, 276 const void *data); 277 void Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset); 278 VkIndexType GetIndexType(); 279 280 protected: 281 VkIndexType m_indexType; 282 }; 283 284 class VkImageObj : public vk_testing::Image { 285 public: 286 VkImageObj(VkDeviceObj *dev); 287 bool IsCompatible(VkFlags usage, VkFlags features); 288 289 public: 290 void init(uint32_t w, uint32_t h, VkFormat fmt, VkFlags usage, 291 VkImageTiling tiling = VK_IMAGE_TILING_LINEAR, 292 VkMemoryPropertyFlags reqs = 0); 293 294 // void clear( CommandBuffer*, uint32_t[4] ); 295 296 void layout(VkImageLayout layout) { 297 m_descriptorImageInfo.imageLayout = layout; 298 } 299 300 VkDeviceMemory memory() const { return Image::memory().handle(); } 301 302 void *MapMemory() { return Image::memory().map(); } 303 304 void UnmapMemory() { Image::memory().unmap(); } 305 306 void ImageMemoryBarrier(VkCommandBufferObj *cmd, VkImageAspectFlags aspect, 307 VkFlags output_mask, VkFlags input_mask, 308 VkImageLayout image_layout); 309 310 VkResult CopyImage(VkImageObj &src_image); 311 312 VkImage image() const { return handle(); } 313 314 VkImageView targetView(VkFormat format) { 315 if (!m_targetView.initialized()) { 316 VkImageViewCreateInfo createView = {}; 317 createView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 318 createView.image = handle(); 319 createView.viewType = VK_IMAGE_VIEW_TYPE_2D; 320 createView.format = format; 321 createView.components.r = VK_COMPONENT_SWIZZLE_R; 322 createView.components.g = VK_COMPONENT_SWIZZLE_G; 323 createView.components.b = VK_COMPONENT_SWIZZLE_B; 324 createView.components.a = VK_COMPONENT_SWIZZLE_A; 325 createView.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 326 1}; 327 createView.flags = 0; 328 m_targetView.init(*m_device, createView); 329 } 330 return m_targetView.handle(); 331 } 332 333 void SetLayout(VkCommandBufferObj *cmd_buf, VkImageAspectFlagBits aspect, 334 VkImageLayout image_layout); 335 void SetLayout(VkImageAspectFlagBits aspect, VkImageLayout image_layout); 336 337 VkImageLayout layout() const { return m_descriptorImageInfo.imageLayout; } 338 uint32_t width() const { return extent().width; } 339 uint32_t height() const { return extent().height; } 340 VkDeviceObj *device() const { return m_device; } 341 342 protected: 343 VkDeviceObj *m_device; 344 345 vk_testing::ImageView m_targetView; 346 VkDescriptorImageInfo m_descriptorImageInfo; 347 }; 348 349 class VkTextureObj : public VkImageObj { 350 public: 351 VkTextureObj(VkDeviceObj *device, uint32_t *colors = NULL); 352 353 VkDescriptorImageInfo m_imageInfo; 354 355 protected: 356 VkDeviceObj *m_device; 357 vk_testing::ImageView m_textureView; 358 VkDeviceSize m_rowPitch; 359 }; 360 361 class VkSamplerObj : public vk_testing::Sampler { 362 public: 363 VkSamplerObj(VkDeviceObj *device); 364 365 protected: 366 VkDeviceObj *m_device; 367 }; 368 369 class VkDescriptorSetObj : public vk_testing::DescriptorPool { 370 public: 371 VkDescriptorSetObj(VkDeviceObj *device); 372 ~VkDescriptorSetObj(); 373 374 int AppendDummy(); 375 int AppendBuffer(VkDescriptorType type, 376 VkConstantBufferObj &constantBuffer); 377 int AppendSamplerTexture(VkSamplerObj *sampler, VkTextureObj *texture); 378 void CreateVKDescriptorSet(VkCommandBufferObj *commandBuffer); 379 380 VkDescriptorSet GetDescriptorSetHandle() const; 381 VkPipelineLayout GetPipelineLayout() const; 382 int GetTypeCounts() {return m_type_counts.size();} 383 384 protected: 385 VkDeviceObj *m_device; 386 vector<VkDescriptorPoolSize> m_type_counts; 387 int m_nextSlot; 388 389 vector<VkDescriptorImageInfo> m_imageSamplerDescriptors; 390 vector<VkWriteDescriptorSet> m_writes; 391 392 vk_testing::DescriptorSetLayout m_layout; 393 vk_testing::PipelineLayout m_pipeline_layout; 394 vk_testing::DescriptorSet *m_set = NULL; 395 }; 396 397 class VkShaderObj : public vk_testing::ShaderModule { 398 public: 399 VkShaderObj(VkDeviceObj *device, const char *shaderText, 400 VkShaderStageFlagBits stage, VkRenderFramework *framework, 401 char const *name = "main"); 402 VkPipelineShaderStageCreateInfo GetStageCreateInfo() const; 403 404 protected: 405 VkPipelineShaderStageCreateInfo stage_info; 406 VkShaderStageFlagBits m_stage; 407 char const *m_name; 408 VkDeviceObj *m_device; 409 }; 410 411 class VkPipelineObj : public vk_testing::Pipeline { 412 public: 413 VkPipelineObj(VkDeviceObj *device); 414 void AddShader(VkShaderObj *shaderObj); 415 void AddVertexInputAttribs(VkVertexInputAttributeDescription *vi_attrib, 416 int count); 417 void AddVertexInputBindings(VkVertexInputBindingDescription *vi_binding, 418 int count); 419 void AddColorAttachment(uint32_t binding, 420 const VkPipelineColorBlendAttachmentState *att); 421 void MakeDynamic(VkDynamicState state); 422 423 void AddColorAttachment() { 424 VkPipelineColorBlendAttachmentState att = {}; 425 att.blendEnable = VK_FALSE; 426 att.colorWriteMask = 0xf; 427 AddColorAttachment(0, &att); 428 } 429 430 void SetDepthStencil(VkPipelineDepthStencilStateCreateInfo *); 431 void SetMSAA(VkPipelineMultisampleStateCreateInfo *ms_state); 432 void SetViewport(vector<VkViewport> viewports); 433 void SetScissor(vector<VkRect2D> scissors); 434 VkResult CreateVKPipeline(VkPipelineLayout layout, 435 VkRenderPass render_pass); 436 437 protected: 438 VkPipelineVertexInputStateCreateInfo m_vi_state; 439 VkPipelineInputAssemblyStateCreateInfo m_ia_state; 440 VkPipelineRasterizationStateCreateInfo m_rs_state; 441 VkPipelineColorBlendStateCreateInfo m_cb_state; 442 VkPipelineDepthStencilStateCreateInfo m_ds_state; 443 VkPipelineViewportStateCreateInfo m_vp_state; 444 VkPipelineMultisampleStateCreateInfo m_ms_state; 445 vector<VkDynamicState> m_dynamic_state_enables; 446 vector<VkViewport> m_viewports; 447 vector<VkRect2D> m_scissors; 448 VkDeviceObj *m_device; 449 vector<VkShaderObj *> m_shaderObjs; 450 vector<int> m_vertexBufferBindings; 451 vector<VkPipelineColorBlendAttachmentState> m_colorAttachments; 452 int m_vertexBufferCount; 453 }; 454 455 #endif // VKRENDERFRAMEWORK_H 456