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 * Copyright (c) 2015-2016 Google, Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and/or associated documentation files (the "Materials"), to 9 * deal in the Materials without restriction, including without limitation the 10 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 * sell copies of the Materials, and to permit persons to whom the Materials are 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice(s) and this permission notice shall be included in 15 * all copies or substantial portions of the Materials. 16 * 17 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 24 * USE OR OTHER DEALINGS IN THE MATERIALS. 25 * 26 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 27 * Author: Tony Barbour <tony (at) LunarG.com> 28 */ 29 30 #include "vkrenderframework.h" 31 32 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 33 #define GET_DEVICE_PROC_ADDR(dev, entrypoint) \ 34 { \ 35 fp##entrypoint = \ 36 (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint); \ 37 assert(fp##entrypoint != NULL); \ 38 } 39 40 VkRenderFramework::VkRenderFramework() 41 : m_commandPool(), m_commandBuffer(), m_renderPass(VK_NULL_HANDLE), 42 m_framebuffer(VK_NULL_HANDLE), m_width(256.0), // default window width 43 m_height(256.0), // default window height 44 m_render_target_fmt(VK_FORMAT_R8G8B8A8_UNORM), 45 m_depth_stencil_fmt(VK_FORMAT_UNDEFINED), m_clear_via_load_op(true), 46 m_depth_clear_color(1.0), m_stencil_clear_color(0), m_depthStencil(NULL), 47 m_CreateDebugReportCallback(VK_NULL_HANDLE), 48 m_DestroyDebugReportCallback(VK_NULL_HANDLE), 49 m_globalMsgCallback(VK_NULL_HANDLE), m_devMsgCallback(VK_NULL_HANDLE) { 50 51 memset(&m_renderPassBeginInfo, 0, sizeof(m_renderPassBeginInfo)); 52 m_renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 53 54 // clear the back buffer to dark grey 55 m_clear_color.float32[0] = 0.25f; 56 m_clear_color.float32[1] = 0.25f; 57 m_clear_color.float32[2] = 0.25f; 58 m_clear_color.float32[3] = 0.0f; 59 } 60 61 VkRenderFramework::~VkRenderFramework() {} 62 63 void VkRenderFramework::InitFramework() { 64 std::vector<const char *> instance_layer_names; 65 std::vector<const char *> device_layer_names; 66 std::vector<const char *> instance_extension_names; 67 std::vector<const char *> device_extension_names; 68 instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME); 69 device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); 70 InitFramework(instance_layer_names, device_layer_names, 71 instance_extension_names, device_extension_names); 72 } 73 74 void VkRenderFramework::InitFramework( 75 std::vector<const char *> instance_layer_names, 76 std::vector<const char *> device_layer_names, 77 std::vector<const char *> instance_extension_names, 78 std::vector<const char *> device_extension_names, 79 PFN_vkDebugReportCallbackEXT dbgFunction, void *userData) { 80 VkInstanceCreateInfo instInfo = {}; 81 std::vector<VkExtensionProperties> instance_extensions; 82 std::vector<VkExtensionProperties> device_extensions; 83 VkResult U_ASSERT_ONLY err; 84 85 /* TODO: Verify requested extensions are available */ 86 87 instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 88 instInfo.pNext = NULL; 89 instInfo.pApplicationInfo = &app_info; 90 instInfo.enabledLayerCount = instance_layer_names.size(); 91 instInfo.ppEnabledLayerNames = instance_layer_names.data(); 92 instInfo.enabledExtensionCount = instance_extension_names.size(); 93 instInfo.ppEnabledExtensionNames = instance_extension_names.data(); 94 err = vkCreateInstance(&instInfo, NULL, &this->inst); 95 ASSERT_VK_SUCCESS(err); 96 97 err = vkEnumeratePhysicalDevices(inst, &this->gpu_count, NULL); 98 ASSERT_LE(this->gpu_count, ARRAY_SIZE(objs)) << "Too many gpus"; 99 ASSERT_VK_SUCCESS(err); 100 err = vkEnumeratePhysicalDevices(inst, &this->gpu_count, objs); 101 ASSERT_VK_SUCCESS(err); 102 ASSERT_GE(this->gpu_count, (uint32_t)1) << "No GPU available"; 103 if (dbgFunction) { 104 m_CreateDebugReportCallback = 105 (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr( 106 this->inst, "vkCreateDebugReportCallbackEXT"); 107 ASSERT_NE(m_CreateDebugReportCallback, 108 (PFN_vkCreateDebugReportCallbackEXT)NULL) 109 << "Did not get function pointer for CreateDebugReportCallback"; 110 if (m_CreateDebugReportCallback) { 111 VkDebugReportCallbackCreateInfoEXT dbgCreateInfo; 112 memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo)); 113 dbgCreateInfo.sType = 114 VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 115 dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | 116 VK_DEBUG_REPORT_WARNING_BIT_EXT | 117 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 118 dbgCreateInfo.pfnCallback = dbgFunction; 119 dbgCreateInfo.pUserData = userData; 120 121 err = m_CreateDebugReportCallback(this->inst, &dbgCreateInfo, NULL, 122 &m_globalMsgCallback); 123 ASSERT_VK_SUCCESS(err); 124 125 m_DestroyDebugReportCallback = 126 (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr( 127 this->inst, "vkDestroyDebugReportCallbackEXT"); 128 ASSERT_NE(m_DestroyDebugReportCallback, 129 (PFN_vkDestroyDebugReportCallbackEXT)NULL) 130 << "Did not get function pointer for " 131 "DestroyDebugReportCallback"; 132 m_DebugReportMessage = 133 (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr( 134 this->inst, "vkDebugReportMessageEXT"); 135 ASSERT_NE(m_DebugReportMessage, (PFN_vkDebugReportMessageEXT)NULL) 136 << "Did not get function pointer for DebugReportMessage"; 137 } 138 } 139 140 /* TODO: Verify requested physical device extensions are available */ 141 m_device = 142 new VkDeviceObj(0, objs[0], device_layer_names, device_extension_names); 143 144 /* Now register callback on device */ 145 if (0) { 146 if (m_CreateDebugReportCallback) { 147 VkDebugReportCallbackCreateInfoEXT dbgInfo; 148 memset(&dbgInfo, 0, sizeof(dbgInfo)); 149 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 150 dbgInfo.pfnCallback = dbgFunction; 151 dbgInfo.pUserData = userData; 152 dbgInfo.flags = 153 VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; 154 err = m_CreateDebugReportCallback(this->inst, &dbgInfo, NULL, 155 &m_devMsgCallback); 156 ASSERT_VK_SUCCESS(err); 157 } 158 } 159 m_device->get_device_queue(); 160 161 m_depthStencil = new VkDepthStencilObj(); 162 } 163 164 void VkRenderFramework::ShutdownFramework() { 165 delete m_commandBuffer; 166 if (m_commandPool) 167 vkDestroyCommandPool(device(), m_commandPool, NULL); 168 if (m_framebuffer) 169 vkDestroyFramebuffer(device(), m_framebuffer, NULL); 170 if (m_renderPass) 171 vkDestroyRenderPass(device(), m_renderPass, NULL); 172 173 if (m_globalMsgCallback) 174 m_DestroyDebugReportCallback(this->inst, m_globalMsgCallback, NULL); 175 if (m_devMsgCallback) 176 m_DestroyDebugReportCallback(this->inst, m_devMsgCallback, NULL); 177 178 while (!m_renderTargets.empty()) { 179 vkDestroyImageView( 180 device(), m_renderTargets.back()->targetView(m_render_target_fmt), 181 NULL); 182 vkDestroyImage(device(), m_renderTargets.back()->image(), NULL); 183 vkFreeMemory(device(), m_renderTargets.back()->memory(), NULL); 184 m_renderTargets.pop_back(); 185 } 186 187 delete m_depthStencil; 188 189 // reset the driver 190 delete m_device; 191 if (this->inst) 192 vkDestroyInstance(this->inst, NULL); 193 } 194 195 void VkRenderFramework::InitState() { 196 VkResult U_ASSERT_ONLY err; 197 198 m_render_target_fmt = VkTestFramework::GetFormat(inst, m_device); 199 200 m_lineWidth = 1.0f; 201 202 m_depthBiasConstantFactor = 0.0f; 203 m_depthBiasClamp = 0.0f; 204 m_depthBiasSlopeFactor = 0.0f; 205 206 m_blendConstants[0] = 1.0f; 207 m_blendConstants[1] = 1.0f; 208 m_blendConstants[2] = 1.0f; 209 m_blendConstants[3] = 1.0f; 210 211 m_minDepthBounds = 0.f; 212 m_maxDepthBounds = 1.f; 213 214 m_compareMask = 0xff; 215 m_writeMask = 0xff; 216 m_reference = 0; 217 218 VkCommandPoolCreateInfo cmd_pool_info; 219 cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 220 cmd_pool_info.pNext = NULL, 221 cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_; 222 cmd_pool_info.flags = 0, 223 err = vkCreateCommandPool(device(), &cmd_pool_info, NULL, &m_commandPool); 224 assert(!err); 225 226 m_commandBuffer = new VkCommandBufferObj(m_device, m_commandPool); 227 } 228 229 void VkRenderFramework::InitViewport(float width, float height) { 230 VkViewport viewport; 231 VkRect2D scissor; 232 viewport.x = 0; 233 viewport.y = 0; 234 viewport.width = 1.f * width; 235 viewport.height = 1.f * height; 236 viewport.minDepth = 0.f; 237 viewport.maxDepth = 1.f; 238 m_viewports.push_back(viewport); 239 240 scissor.extent.width = (int32_t)width; 241 scissor.extent.height = (int32_t)height; 242 scissor.offset.x = 0; 243 scissor.offset.y = 0; 244 m_scissors.push_back(scissor); 245 246 m_width = width; 247 m_height = height; 248 } 249 250 void VkRenderFramework::InitViewport() { InitViewport(m_width, m_height); } 251 void VkRenderFramework::InitRenderTarget() { InitRenderTarget(1); } 252 253 void VkRenderFramework::InitRenderTarget(uint32_t targets) { 254 InitRenderTarget(targets, NULL); 255 } 256 257 void VkRenderFramework::InitRenderTarget(VkImageView *dsBinding) { 258 InitRenderTarget(1, dsBinding); 259 } 260 261 void VkRenderFramework::InitRenderTarget(uint32_t targets, 262 VkImageView *dsBinding) { 263 std::vector<VkAttachmentDescription> attachments; 264 std::vector<VkAttachmentReference> color_references; 265 std::vector<VkImageView> bindings; 266 attachments.reserve(targets + 1); // +1 for dsBinding 267 color_references.reserve(targets); 268 bindings.reserve(targets + 1); // +1 for dsBinding 269 270 VkAttachmentDescription att = {}; 271 att.format = m_render_target_fmt; 272 att.samples = VK_SAMPLE_COUNT_1_BIT; 273 att.loadOp = (m_clear_via_load_op) ? VK_ATTACHMENT_LOAD_OP_CLEAR 274 : VK_ATTACHMENT_LOAD_OP_LOAD; 275 att.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 276 att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 277 att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 278 att.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 279 att.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 280 281 VkAttachmentReference ref = {}; 282 ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 283 284 m_renderPassClearValues.clear(); 285 VkClearValue clear = {}; 286 clear.color = m_clear_color; 287 288 VkImageView bind = {}; 289 290 for (uint32_t i = 0; i < targets; i++) { 291 attachments.push_back(att); 292 293 ref.attachment = i; 294 color_references.push_back(ref); 295 296 m_renderPassClearValues.push_back(clear); 297 298 VkImageObj *img = new VkImageObj(m_device); 299 300 VkFormatProperties props; 301 302 vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), 303 m_render_target_fmt, &props); 304 305 if (props.linearTilingFeatures & 306 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) { 307 img->init((uint32_t)m_width, (uint32_t)m_height, 308 m_render_target_fmt, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 309 VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 310 VK_IMAGE_TILING_LINEAR); 311 } else if (props.optimalTilingFeatures & 312 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) { 313 img->init((uint32_t)m_width, (uint32_t)m_height, 314 m_render_target_fmt, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 315 VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 316 VK_IMAGE_TILING_OPTIMAL); 317 } else { 318 FAIL() << "Neither Linear nor Optimal allowed for render target"; 319 } 320 321 m_renderTargets.push_back(img); 322 bind = img->targetView(m_render_target_fmt); 323 bindings.push_back(bind); 324 } 325 326 VkSubpassDescription subpass = {}; 327 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 328 subpass.flags = 0; 329 subpass.inputAttachmentCount = 0; 330 subpass.pInputAttachments = NULL; 331 subpass.colorAttachmentCount = targets; 332 subpass.pColorAttachments = color_references.data(); 333 subpass.pResolveAttachments = NULL; 334 335 VkAttachmentReference ds_reference; 336 if (dsBinding) { 337 att.format = m_depth_stencil_fmt; 338 att.loadOp = (m_clear_via_load_op) ? VK_ATTACHMENT_LOAD_OP_CLEAR 339 : VK_ATTACHMENT_LOAD_OP_LOAD; 340 ; 341 att.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 342 att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 343 att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; 344 att.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 345 att.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 346 attachments.push_back(att); 347 348 clear.depthStencil.depth = m_depth_clear_color; 349 clear.depthStencil.stencil = m_stencil_clear_color; 350 m_renderPassClearValues.push_back(clear); 351 352 bindings.push_back(*dsBinding); 353 354 ds_reference.attachment = targets; 355 ds_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 356 subpass.pDepthStencilAttachment = &ds_reference; 357 } else { 358 subpass.pDepthStencilAttachment = NULL; 359 } 360 361 subpass.preserveAttachmentCount = 0; 362 subpass.pPreserveAttachments = NULL; 363 364 VkRenderPassCreateInfo rp_info = {}; 365 rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 366 rp_info.attachmentCount = attachments.size(); 367 rp_info.pAttachments = attachments.data(); 368 rp_info.subpassCount = 1; 369 rp_info.pSubpasses = &subpass; 370 371 vkCreateRenderPass(device(), &rp_info, NULL, &m_renderPass); 372 373 // Create Framebuffer and RenderPass with color attachments and any 374 // depth/stencil attachment 375 VkFramebufferCreateInfo fb_info = {}; 376 fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 377 fb_info.pNext = NULL; 378 fb_info.renderPass = m_renderPass; 379 fb_info.attachmentCount = bindings.size(); 380 fb_info.pAttachments = bindings.data(); 381 fb_info.width = (uint32_t)m_width; 382 fb_info.height = (uint32_t)m_height; 383 fb_info.layers = 1; 384 385 vkCreateFramebuffer(device(), &fb_info, NULL, &m_framebuffer); 386 387 m_renderPassBeginInfo.renderPass = m_renderPass; 388 m_renderPassBeginInfo.framebuffer = m_framebuffer; 389 m_renderPassBeginInfo.renderArea.extent.width = (int32_t)m_width; 390 m_renderPassBeginInfo.renderArea.extent.height = (int32_t)m_height; 391 m_renderPassBeginInfo.clearValueCount = m_renderPassClearValues.size(); 392 m_renderPassBeginInfo.pClearValues = m_renderPassClearValues.data(); 393 } 394 395 VkDeviceObj::VkDeviceObj(uint32_t id, VkPhysicalDevice obj) 396 : vk_testing::Device(obj), id(id) { 397 init(); 398 399 props = phy().properties(); 400 queue_props = phy().queue_properties().data(); 401 } 402 403 VkDeviceObj::VkDeviceObj(uint32_t id, VkPhysicalDevice obj, 404 std::vector<const char *> &layer_names, 405 std::vector<const char *> &extension_names) 406 : vk_testing::Device(obj), id(id) { 407 init(layer_names, extension_names); 408 409 props = phy().properties(); 410 queue_props = phy().queue_properties().data(); 411 } 412 413 void VkDeviceObj::get_device_queue() { 414 ASSERT_NE(true, graphics_queues().empty()); 415 m_queue = graphics_queues()[0]->handle(); 416 } 417 418 VkDescriptorSetObj::VkDescriptorSetObj(VkDeviceObj *device) 419 : m_device(device), m_nextSlot(0) {} 420 421 VkDescriptorSetObj::~VkDescriptorSetObj() { 422 if (m_set) { 423 delete m_set; 424 } 425 } 426 427 int VkDescriptorSetObj::AppendDummy() { 428 /* request a descriptor but do not update it */ 429 VkDescriptorPoolSize tc = {}; 430 tc.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 431 tc.descriptorCount = 1; 432 m_type_counts.push_back(tc); 433 434 return m_nextSlot++; 435 } 436 437 int VkDescriptorSetObj::AppendBuffer(VkDescriptorType type, 438 VkConstantBufferObj &constantBuffer) { 439 assert(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || 440 type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || 441 type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || 442 type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC); 443 VkDescriptorPoolSize tc = {}; 444 tc.type = type; 445 tc.descriptorCount = 1; 446 m_type_counts.push_back(tc); 447 448 m_writes.push_back(vk_testing::Device::write_descriptor_set( 449 vk_testing::DescriptorSet(), m_nextSlot, 0, type, 1, 450 &constantBuffer.m_descriptorBufferInfo)); 451 452 return m_nextSlot++; 453 } 454 455 int VkDescriptorSetObj::AppendSamplerTexture(VkSamplerObj *sampler, 456 VkTextureObj *texture) { 457 VkDescriptorPoolSize tc = {}; 458 tc.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 459 tc.descriptorCount = 1; 460 m_type_counts.push_back(tc); 461 462 VkDescriptorImageInfo tmp = texture->m_imageInfo; 463 tmp.sampler = sampler->handle(); 464 m_imageSamplerDescriptors.push_back(tmp); 465 466 m_writes.push_back(vk_testing::Device::write_descriptor_set( 467 vk_testing::DescriptorSet(), m_nextSlot, 0, 468 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &tmp)); 469 470 return m_nextSlot++; 471 } 472 473 VkPipelineLayout VkDescriptorSetObj::GetPipelineLayout() const { 474 return m_pipeline_layout.handle(); 475 } 476 477 VkDescriptorSet VkDescriptorSetObj::GetDescriptorSetHandle() const { 478 return m_set->handle(); 479 } 480 481 void VkDescriptorSetObj::CreateVKDescriptorSet( 482 VkCommandBufferObj *commandBuffer) { 483 484 if ( m_type_counts.size()) { 485 // create VkDescriptorPool 486 VkDescriptorPoolCreateInfo pool = {}; 487 pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 488 pool.poolSizeCount = m_type_counts.size(); 489 pool.maxSets = 1; 490 pool.pPoolSizes = m_type_counts.data(); 491 init(*m_device, pool); 492 } 493 494 // create VkDescriptorSetLayout 495 vector<VkDescriptorSetLayoutBinding> bindings; 496 bindings.resize(m_type_counts.size()); 497 for (size_t i = 0; i < m_type_counts.size(); i++) { 498 bindings[i].binding = i; 499 bindings[i].descriptorType = m_type_counts[i].type; 500 bindings[i].descriptorCount = m_type_counts[i].descriptorCount; 501 bindings[i].stageFlags = VK_SHADER_STAGE_ALL; 502 bindings[i].pImmutableSamplers = NULL; 503 } 504 505 // create VkDescriptorSetLayout 506 VkDescriptorSetLayoutCreateInfo layout = {}; 507 layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 508 layout.bindingCount = bindings.size(); 509 layout.pBindings = bindings.data(); 510 511 m_layout.init(*m_device, layout); 512 vector<const vk_testing::DescriptorSetLayout *> layouts; 513 layouts.push_back(&m_layout); 514 515 // create VkPipelineLayout 516 VkPipelineLayoutCreateInfo pipeline_layout = {}; 517 pipeline_layout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 518 pipeline_layout.setLayoutCount = layouts.size(); 519 pipeline_layout.pSetLayouts = NULL; 520 521 m_pipeline_layout.init(*m_device, pipeline_layout, layouts); 522 523 if (m_type_counts.size()) { 524 // create VkDescriptorSet 525 m_set = alloc_sets(*m_device, m_layout); 526 527 // build the update array 528 size_t imageSamplerCount = 0; 529 for (std::vector<VkWriteDescriptorSet>::iterator it = m_writes.begin(); 530 it != m_writes.end(); it++) { 531 it->dstSet = m_set->handle(); 532 if (it->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 533 it->pImageInfo = &m_imageSamplerDescriptors[imageSamplerCount++]; 534 } 535 536 // do the updates 537 m_device->update_descriptor_sets(m_writes); 538 } 539 } 540 541 VkImageObj::VkImageObj(VkDeviceObj *dev) { 542 m_device = dev; 543 m_descriptorImageInfo.imageView = VK_NULL_HANDLE; 544 m_descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; 545 } 546 547 void VkImageObj::ImageMemoryBarrier(VkCommandBufferObj *cmd_buf, 548 VkImageAspectFlags aspect, 549 VkFlags output_mask /*= 550 VK_ACCESS_HOST_WRITE_BIT | 551 VK_ACCESS_SHADER_WRITE_BIT | 552 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 553 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 554 VK_MEMORY_OUTPUT_COPY_BIT*/, 555 VkFlags input_mask /*= 556 VK_ACCESS_HOST_READ_BIT | 557 VK_ACCESS_INDIRECT_COMMAND_READ_BIT | 558 VK_ACCESS_INDEX_READ_BIT | 559 VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | 560 VK_ACCESS_UNIFORM_READ_BIT | 561 VK_ACCESS_SHADER_READ_BIT | 562 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 563 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | 564 VK_MEMORY_INPUT_COPY_BIT*/, 565 VkImageLayout image_layout) { 566 const VkImageSubresourceRange subresourceRange = 567 subresource_range(aspect, 0, 1, 0, 1); 568 VkImageMemoryBarrier barrier; 569 barrier = image_memory_barrier(output_mask, input_mask, layout(), 570 image_layout, subresourceRange); 571 572 VkImageMemoryBarrier *pmemory_barrier = &barrier; 573 574 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 575 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 576 577 // write barrier to the command buffer 578 vkCmdPipelineBarrier(cmd_buf->handle(), src_stages, dest_stages, 0, 0, NULL, 579 0, NULL, 1, pmemory_barrier); 580 } 581 582 void VkImageObj::SetLayout(VkCommandBufferObj *cmd_buf, 583 VkImageAspectFlagBits aspect, 584 VkImageLayout image_layout) { 585 VkFlags src_mask, dst_mask; 586 const VkFlags all_cache_outputs = 587 VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | 588 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 589 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 590 VK_ACCESS_TRANSFER_WRITE_BIT; 591 const VkFlags all_cache_inputs = 592 VK_ACCESS_HOST_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT | 593 VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | 594 VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT | 595 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 596 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_MEMORY_READ_BIT; 597 598 if (image_layout == m_descriptorImageInfo.imageLayout) { 599 return; 600 } 601 602 switch (image_layout) { 603 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: 604 if (m_descriptorImageInfo.imageLayout == 605 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) 606 src_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 607 else 608 src_mask = VK_ACCESS_TRANSFER_WRITE_BIT; 609 dst_mask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT; 610 break; 611 612 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: 613 if (m_descriptorImageInfo.imageLayout == 614 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) 615 src_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 616 else if (m_descriptorImageInfo.imageLayout == 617 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) 618 src_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; 619 else 620 src_mask = VK_ACCESS_TRANSFER_WRITE_BIT; 621 dst_mask = VK_ACCESS_TRANSFER_WRITE_BIT; 622 break; 623 624 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: 625 if (m_descriptorImageInfo.imageLayout == 626 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) 627 src_mask = VK_ACCESS_TRANSFER_WRITE_BIT; 628 else 629 src_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; 630 dst_mask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_MEMORY_READ_BIT; 631 break; 632 633 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: 634 if (m_descriptorImageInfo.imageLayout == 635 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) 636 src_mask = VK_ACCESS_TRANSFER_READ_BIT; 637 else 638 src_mask = 0; 639 dst_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 640 break; 641 642 default: 643 src_mask = all_cache_outputs; 644 dst_mask = all_cache_inputs; 645 break; 646 } 647 648 ImageMemoryBarrier(cmd_buf, aspect, src_mask, dst_mask, image_layout); 649 m_descriptorImageInfo.imageLayout = image_layout; 650 } 651 652 void VkImageObj::SetLayout(VkImageAspectFlagBits aspect, 653 VkImageLayout image_layout) { 654 VkResult U_ASSERT_ONLY err; 655 656 if (image_layout == m_descriptorImageInfo.imageLayout) { 657 return; 658 } 659 660 VkCommandPoolCreateInfo cmd_pool_info = {}; 661 cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 662 cmd_pool_info.pNext = NULL; 663 cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_; 664 cmd_pool_info.flags = 0; 665 vk_testing::CommandPool pool(*m_device, cmd_pool_info); 666 VkCommandBufferObj cmd_buf(m_device, pool.handle()); 667 668 /* Build command buffer to set image layout in the driver */ 669 err = cmd_buf.BeginCommandBuffer(); 670 assert(!err); 671 672 SetLayout(&cmd_buf, aspect, image_layout); 673 674 err = cmd_buf.EndCommandBuffer(); 675 assert(!err); 676 677 cmd_buf.QueueCommandBuffer(); 678 } 679 680 bool VkImageObj::IsCompatible(VkFlags usage, VkFlags features) { 681 if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) && 682 !(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) 683 return false; 684 685 return true; 686 } 687 688 void VkImageObj::init(uint32_t w, uint32_t h, VkFormat fmt, VkFlags usage, 689 VkImageTiling requested_tiling, 690 VkMemoryPropertyFlags reqs) { 691 VkFormatProperties image_fmt; 692 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; 693 694 vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), fmt, 695 &image_fmt); 696 697 if (requested_tiling == VK_IMAGE_TILING_LINEAR) { 698 if (IsCompatible(usage, image_fmt.linearTilingFeatures)) { 699 tiling = VK_IMAGE_TILING_LINEAR; 700 } else if (IsCompatible(usage, image_fmt.optimalTilingFeatures)) { 701 tiling = VK_IMAGE_TILING_OPTIMAL; 702 } else { 703 ASSERT_TRUE(false) 704 << "Error: Cannot find requested tiling configuration"; 705 } 706 } else if (IsCompatible(usage, image_fmt.optimalTilingFeatures)) { 707 tiling = VK_IMAGE_TILING_OPTIMAL; 708 } else if (IsCompatible(usage, image_fmt.linearTilingFeatures)) { 709 tiling = VK_IMAGE_TILING_LINEAR; 710 } else { 711 ASSERT_TRUE(false) 712 << "Error: Cannot find requested tiling configuration"; 713 } 714 715 VkImageCreateInfo imageCreateInfo = vk_testing::Image::create_info(); 716 imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; 717 imageCreateInfo.format = fmt; 718 imageCreateInfo.extent.width = w; 719 imageCreateInfo.extent.height = h; 720 imageCreateInfo.mipLevels = 1; 721 imageCreateInfo.tiling = tiling; 722 imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 723 724 layout(imageCreateInfo.initialLayout); 725 imageCreateInfo.usage = usage; 726 727 vk_testing::Image::init(*m_device, imageCreateInfo, reqs); 728 729 VkImageLayout newLayout; 730 if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) 731 newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 732 else if (usage & VK_IMAGE_USAGE_SAMPLED_BIT) 733 newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 734 else 735 newLayout = m_descriptorImageInfo.imageLayout; 736 737 SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, newLayout); 738 } 739 740 VkResult VkImageObj::CopyImage(VkImageObj &src_image) { 741 VkResult U_ASSERT_ONLY err; 742 VkImageLayout src_image_layout, dest_image_layout; 743 744 VkCommandPoolCreateInfo cmd_pool_info = {}; 745 cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 746 cmd_pool_info.pNext = NULL; 747 cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_; 748 cmd_pool_info.flags = 0; 749 vk_testing::CommandPool pool(*m_device, cmd_pool_info); 750 VkCommandBufferObj cmd_buf(m_device, pool.handle()); 751 752 /* Build command buffer to copy staging texture to usable texture */ 753 err = cmd_buf.BeginCommandBuffer(); 754 assert(!err); 755 756 /* TODO: Can we determine image aspect from image object? */ 757 src_image_layout = src_image.layout(); 758 src_image.SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, 759 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 760 761 dest_image_layout = this->layout(); 762 this->SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, 763 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 764 765 VkImageCopy copy_region = {}; 766 copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 767 copy_region.srcSubresource.baseArrayLayer = 0; 768 copy_region.srcSubresource.mipLevel = 0; 769 copy_region.srcSubresource.layerCount = 1; 770 copy_region.srcOffset.x = 0; 771 copy_region.srcOffset.y = 0; 772 copy_region.srcOffset.z = 0; 773 copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 774 copy_region.dstSubresource.baseArrayLayer = 0; 775 copy_region.dstSubresource.mipLevel = 0; 776 copy_region.dstSubresource.layerCount = 1; 777 copy_region.dstOffset.x = 0; 778 copy_region.dstOffset.y = 0; 779 copy_region.dstOffset.z = 0; 780 copy_region.extent = src_image.extent(); 781 782 vkCmdCopyImage(cmd_buf.handle(), src_image.handle(), src_image.layout(), 783 handle(), layout(), 1, ©_region); 784 785 src_image.SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, src_image_layout); 786 787 this->SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, dest_image_layout); 788 789 err = cmd_buf.EndCommandBuffer(); 790 assert(!err); 791 792 cmd_buf.QueueCommandBuffer(); 793 794 return VK_SUCCESS; 795 } 796 797 VkTextureObj::VkTextureObj(VkDeviceObj *device, uint32_t *colors) 798 : VkImageObj(device) { 799 m_device = device; 800 const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; 801 uint32_t tex_colors[2] = {0xffff0000, 0xff00ff00}; 802 void *data; 803 uint32_t x, y; 804 VkImageObj stagingImage(device); 805 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 806 807 stagingImage.init(16, 16, tex_format, VK_IMAGE_USAGE_TRANSFER_DST_BIT | 808 VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 809 VK_IMAGE_TILING_LINEAR, reqs); 810 VkSubresourceLayout layout = stagingImage.subresource_layout( 811 subresource(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0)); 812 813 if (colors == NULL) 814 colors = tex_colors; 815 816 memset(&m_imageInfo, 0, sizeof(m_imageInfo)); 817 818 VkImageViewCreateInfo view = {}; 819 view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 820 view.pNext = NULL; 821 view.image = VK_NULL_HANDLE; 822 view.viewType = VK_IMAGE_VIEW_TYPE_2D; 823 view.format = tex_format; 824 view.components.r = VK_COMPONENT_SWIZZLE_R; 825 view.components.g = VK_COMPONENT_SWIZZLE_G; 826 view.components.b = VK_COMPONENT_SWIZZLE_B; 827 view.components.a = VK_COMPONENT_SWIZZLE_A; 828 view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 829 view.subresourceRange.baseMipLevel = 0; 830 view.subresourceRange.levelCount = 1; 831 view.subresourceRange.baseArrayLayer = 0; 832 view.subresourceRange.layerCount = 1; 833 834 /* create image */ 835 init(16, 16, tex_format, 836 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 837 VK_IMAGE_TILING_OPTIMAL); 838 stagingImage.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL); 839 840 /* create image view */ 841 view.image = handle(); 842 m_textureView.init(*m_device, view); 843 m_imageInfo.imageView = m_textureView.handle(); 844 845 data = stagingImage.MapMemory(); 846 847 for (y = 0; y < extent().height; y++) { 848 uint32_t *row = (uint32_t *)((char *)data + layout.rowPitch * y); 849 for (x = 0; x < extent().width; x++) 850 row[x] = colors[(x & 1) ^ (y & 1)]; 851 } 852 stagingImage.UnmapMemory(); 853 stagingImage.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 854 VkImageObj::CopyImage(stagingImage); 855 } 856 857 VkSamplerObj::VkSamplerObj(VkDeviceObj *device) { 858 m_device = device; 859 860 VkSamplerCreateInfo samplerCreateInfo; 861 memset(&samplerCreateInfo, 0, sizeof(samplerCreateInfo)); 862 samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 863 samplerCreateInfo.magFilter = VK_FILTER_NEAREST; 864 samplerCreateInfo.minFilter = VK_FILTER_NEAREST; 865 samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; 866 samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; 867 samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; 868 samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; 869 samplerCreateInfo.mipLodBias = 0.0; 870 samplerCreateInfo.anisotropyEnable = VK_FALSE; 871 samplerCreateInfo.maxAnisotropy = 1; 872 samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER; 873 samplerCreateInfo.minLod = 0.0; 874 samplerCreateInfo.maxLod = 0.0; 875 samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; 876 samplerCreateInfo.unnormalizedCoordinates = VK_FALSE; 877 878 init(*m_device, samplerCreateInfo); 879 } 880 881 /* 882 * Basic ConstantBuffer constructor. Then use create methods to fill in the 883 * details. 884 */ 885 VkConstantBufferObj::VkConstantBufferObj(VkDeviceObj *device) { 886 m_device = device; 887 m_commandBuffer = 0; 888 889 memset(&m_descriptorBufferInfo, 0, sizeof(m_descriptorBufferInfo)); 890 } 891 892 VkConstantBufferObj::~VkConstantBufferObj() { 893 // TODO: Should we call QueueRemoveMemReference for the constant buffer 894 // memory here? 895 if (m_commandBuffer) { 896 delete m_commandBuffer; 897 delete m_commandPool; 898 } 899 } 900 901 VkConstantBufferObj::VkConstantBufferObj(VkDeviceObj *device, int constantCount, 902 int constantSize, const void *data) { 903 m_device = device; 904 m_commandBuffer = 0; 905 906 memset(&m_descriptorBufferInfo, 0, sizeof(m_descriptorBufferInfo)); 907 m_numVertices = constantCount; 908 m_stride = constantSize; 909 910 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 911 const size_t allocationSize = constantCount * constantSize; 912 init_as_src_and_dst(*m_device, allocationSize, reqs); 913 914 void *pData = memory().map(); 915 memcpy(pData, data, allocationSize); 916 memory().unmap(); 917 918 /* 919 * Constant buffers are going to be used as vertex input buffers 920 * or as shader uniform buffers. So, we'll create the shaderbuffer 921 * descriptor here so it's ready if needed. 922 */ 923 this->m_descriptorBufferInfo.buffer = handle(); 924 this->m_descriptorBufferInfo.offset = 0; 925 this->m_descriptorBufferInfo.range = allocationSize; 926 } 927 928 void VkConstantBufferObj::Bind(VkCommandBuffer commandBuffer, 929 VkDeviceSize offset, uint32_t binding) { 930 vkCmdBindVertexBuffers(commandBuffer, binding, 1, &handle(), &offset); 931 } 932 933 void VkConstantBufferObj::BufferMemoryBarrier(VkFlags srcAccessMask /*= 934 VK_ACCESS_HOST_WRITE_BIT | 935 VK_ACCESS_SHADER_WRITE_BIT | 936 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 937 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 938 VK_MEMORY_OUTPUT_COPY_BIT*/, 939 VkFlags dstAccessMask /*= 940 VK_ACCESS_HOST_READ_BIT | 941 VK_ACCESS_INDIRECT_COMMAND_READ_BIT | 942 VK_ACCESS_INDEX_READ_BIT | 943 VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | 944 VK_ACCESS_UNIFORM_READ_BIT | 945 VK_ACCESS_SHADER_READ_BIT | 946 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 947 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | 948 VK_MEMORY_INPUT_COPY_BIT*/) { 949 VkResult err = VK_SUCCESS; 950 951 if (!m_commandBuffer) { 952 m_fence.init(*m_device, vk_testing::Fence::create_info()); 953 VkCommandPoolCreateInfo cmd_pool_info = {}; 954 cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 955 cmd_pool_info.pNext = NULL; 956 cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_; 957 cmd_pool_info.flags = 0; 958 m_commandPool = new vk_testing::CommandPool(*m_device, cmd_pool_info); 959 m_commandBuffer = 960 new VkCommandBufferObj(m_device, m_commandPool->handle()); 961 } else { 962 m_device->wait(m_fence); 963 } 964 965 // open the command buffer 966 VkCommandBufferBeginInfo cmd_buf_info = {}; 967 VkCommandBufferInheritanceInfo cmd_buf_hinfo = {}; 968 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 969 cmd_buf_info.pNext = NULL; 970 cmd_buf_info.flags = 0; 971 cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo; 972 973 cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; 974 cmd_buf_hinfo.pNext = NULL; 975 cmd_buf_hinfo.renderPass = VK_NULL_HANDLE; 976 cmd_buf_hinfo.subpass = 0; 977 cmd_buf_hinfo.framebuffer = VK_NULL_HANDLE; 978 cmd_buf_hinfo.occlusionQueryEnable = VK_FALSE; 979 cmd_buf_hinfo.queryFlags = 0; 980 cmd_buf_hinfo.pipelineStatistics = 0; 981 982 err = m_commandBuffer->BeginCommandBuffer(&cmd_buf_info); 983 ASSERT_VK_SUCCESS(err); 984 985 VkBufferMemoryBarrier memory_barrier = buffer_memory_barrier( 986 srcAccessMask, dstAccessMask, 0, m_numVertices * m_stride); 987 VkBufferMemoryBarrier *pmemory_barrier = &memory_barrier; 988 989 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 990 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 991 992 // write barrier to the command buffer 993 m_commandBuffer->PipelineBarrier(src_stages, dest_stages, 0, 0, NULL, 1, 994 pmemory_barrier, 0, NULL); 995 996 // finish recording the command buffer 997 err = m_commandBuffer->EndCommandBuffer(); 998 ASSERT_VK_SUCCESS(err); 999 1000 // submit the command buffer to the universal queue 1001 VkCommandBuffer bufferArray[1]; 1002 bufferArray[0] = m_commandBuffer->GetBufferHandle(); 1003 VkSubmitInfo submit_info; 1004 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 1005 submit_info.pNext = NULL; 1006 submit_info.waitSemaphoreCount = 0; 1007 submit_info.pWaitSemaphores = NULL; 1008 submit_info.pWaitDstStageMask = NULL; 1009 submit_info.commandBufferCount = 1; 1010 submit_info.pCommandBuffers = bufferArray; 1011 submit_info.signalSemaphoreCount = 0; 1012 submit_info.pSignalSemaphores = NULL; 1013 1014 err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, m_fence.handle()); 1015 ASSERT_VK_SUCCESS(err); 1016 } 1017 1018 VkIndexBufferObj::VkIndexBufferObj(VkDeviceObj *device) 1019 : VkConstantBufferObj(device) {} 1020 1021 void VkIndexBufferObj::CreateAndInitBuffer(int numIndexes, 1022 VkIndexType indexType, 1023 const void *data) { 1024 m_numVertices = numIndexes; 1025 m_indexType = indexType; 1026 switch (indexType) { 1027 case VK_INDEX_TYPE_UINT16: 1028 m_stride = 2; 1029 break; 1030 case VK_INDEX_TYPE_UINT32: 1031 m_stride = 4; 1032 break; 1033 default: 1034 assert(!"unknown index type"); 1035 m_stride = 2; 1036 break; 1037 } 1038 1039 const size_t allocationSize = numIndexes * m_stride; 1040 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 1041 init_as_src_and_dst(*m_device, allocationSize, reqs); 1042 1043 void *pData = memory().map(); 1044 memcpy(pData, data, allocationSize); 1045 memory().unmap(); 1046 1047 // set up the descriptor for the constant buffer 1048 this->m_descriptorBufferInfo.buffer = handle(); 1049 this->m_descriptorBufferInfo.offset = 0; 1050 this->m_descriptorBufferInfo.range = allocationSize; 1051 } 1052 1053 void VkIndexBufferObj::Bind(VkCommandBuffer commandBuffer, 1054 VkDeviceSize offset) { 1055 vkCmdBindIndexBuffer(commandBuffer, handle(), offset, m_indexType); 1056 } 1057 1058 VkIndexType VkIndexBufferObj::GetIndexType() { return m_indexType; } 1059 1060 VkPipelineShaderStageCreateInfo VkShaderObj::GetStageCreateInfo() const { 1061 VkPipelineShaderStageCreateInfo stageInfo = {}; 1062 1063 stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1064 stageInfo.stage = m_stage; 1065 stageInfo.module = handle(); 1066 stageInfo.pName = m_name; 1067 1068 return stageInfo; 1069 } 1070 1071 VkShaderObj::VkShaderObj(VkDeviceObj *device, const char *shader_code, 1072 VkShaderStageFlagBits stage, 1073 VkRenderFramework *framework, 1074 char const *name) { 1075 VkResult U_ASSERT_ONLY err = VK_SUCCESS; 1076 std::vector<unsigned int> spv; 1077 VkShaderModuleCreateInfo moduleCreateInfo; 1078 size_t shader_len; 1079 1080 m_stage = stage; 1081 m_device = device; 1082 m_name = name; 1083 1084 moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 1085 moduleCreateInfo.pNext = NULL; 1086 1087 if (framework->m_use_glsl) { 1088 1089 shader_len = strlen(shader_code); 1090 moduleCreateInfo.codeSize = 3 * sizeof(uint32_t) + shader_len + 1; 1091 moduleCreateInfo.pCode = (uint32_t *)malloc(moduleCreateInfo.codeSize); 1092 moduleCreateInfo.flags = 0; 1093 1094 /* try version 0 first: VkShaderStage followed by GLSL */ 1095 ((uint32_t *)moduleCreateInfo.pCode)[0] = ICD_SPV_MAGIC; 1096 ((uint32_t *)moduleCreateInfo.pCode)[1] = 0; 1097 ((uint32_t *)moduleCreateInfo.pCode)[2] = stage; 1098 memcpy(((uint32_t *)moduleCreateInfo.pCode + 3), shader_code, 1099 shader_len + 1); 1100 1101 } else { 1102 1103 // Use Reference GLSL to SPV compiler 1104 framework->GLSLtoSPV(stage, shader_code, spv); 1105 moduleCreateInfo.pCode = spv.data(); 1106 moduleCreateInfo.codeSize = spv.size() * sizeof(unsigned int); 1107 moduleCreateInfo.flags = 0; 1108 } 1109 1110 err = init_try(*m_device, moduleCreateInfo); 1111 assert(VK_SUCCESS == err); 1112 } 1113 1114 VkPipelineObj::VkPipelineObj(VkDeviceObj *device) { 1115 m_device = device; 1116 1117 m_vi_state.pNext = VK_NULL_HANDLE; 1118 m_vi_state.vertexBindingDescriptionCount = 0; 1119 m_vi_state.pVertexBindingDescriptions = VK_NULL_HANDLE; 1120 m_vi_state.vertexAttributeDescriptionCount = 0; 1121 m_vi_state.pVertexAttributeDescriptions = VK_NULL_HANDLE; 1122 1123 m_vertexBufferCount = 0; 1124 1125 m_ia_state.sType = 1126 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 1127 m_ia_state.pNext = VK_NULL_HANDLE; 1128 m_ia_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1129 m_ia_state.primitiveRestartEnable = VK_FALSE; 1130 1131 m_rs_state.sType = 1132 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 1133 m_rs_state.pNext = VK_NULL_HANDLE; 1134 m_rs_state.depthClampEnable = VK_TRUE; 1135 m_rs_state.rasterizerDiscardEnable = VK_FALSE; 1136 m_rs_state.polygonMode = VK_POLYGON_MODE_FILL; 1137 m_rs_state.cullMode = VK_CULL_MODE_BACK_BIT; 1138 m_rs_state.frontFace = VK_FRONT_FACE_CLOCKWISE; 1139 m_rs_state.depthBiasEnable = VK_FALSE; 1140 m_rs_state.lineWidth = 1.0f; 1141 m_rs_state.depthBiasConstantFactor = 0.0f; 1142 m_rs_state.depthBiasClamp = 0.0f; 1143 m_rs_state.depthBiasSlopeFactor = 0.0f; 1144 1145 memset(&m_cb_state, 0, sizeof(m_cb_state)); 1146 m_cb_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 1147 m_cb_state.pNext = VK_NULL_HANDLE; 1148 m_cb_state.logicOp = VK_LOGIC_OP_COPY; 1149 m_cb_state.blendConstants[0] = 1.0f; 1150 m_cb_state.blendConstants[1] = 1.0f; 1151 m_cb_state.blendConstants[2] = 1.0f; 1152 m_cb_state.blendConstants[3] = 1.0f; 1153 1154 m_ms_state.pNext = VK_NULL_HANDLE; 1155 m_ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 1156 m_ms_state.pSampleMask = NULL; 1157 m_ms_state.alphaToCoverageEnable = VK_FALSE; 1158 m_ms_state.alphaToOneEnable = VK_FALSE; 1159 m_ms_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 1160 m_ms_state.minSampleShading = 0; 1161 m_ms_state.sampleShadingEnable = 0; 1162 1163 m_vp_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 1164 m_vp_state.pNext = VK_NULL_HANDLE; 1165 m_vp_state.viewportCount = 1; 1166 m_vp_state.scissorCount = 1; 1167 m_vp_state.pViewports = NULL; 1168 m_vp_state.pScissors = NULL; 1169 1170 m_ds_state.sType = 1171 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 1172 m_ds_state.pNext = VK_NULL_HANDLE, m_ds_state.depthTestEnable = VK_FALSE; 1173 m_ds_state.depthWriteEnable = VK_FALSE; 1174 m_ds_state.depthBoundsTestEnable = VK_FALSE; 1175 m_ds_state.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 1176 m_ds_state.back.depthFailOp = VK_STENCIL_OP_KEEP; 1177 m_ds_state.back.failOp = VK_STENCIL_OP_KEEP; 1178 m_ds_state.back.passOp = VK_STENCIL_OP_KEEP; 1179 m_ds_state.back.compareOp = VK_COMPARE_OP_ALWAYS; 1180 m_ds_state.stencilTestEnable = VK_FALSE; 1181 m_ds_state.back.compareMask = 0xff; 1182 m_ds_state.back.writeMask = 0xff; 1183 m_ds_state.back.reference = 0; 1184 m_ds_state.minDepthBounds = 0.f; 1185 m_ds_state.maxDepthBounds = 1.f; 1186 1187 m_ds_state.front = m_ds_state.back; 1188 }; 1189 1190 void VkPipelineObj::AddShader(VkShaderObj *shader) { 1191 m_shaderObjs.push_back(shader); 1192 } 1193 1194 void VkPipelineObj::AddVertexInputAttribs( 1195 VkVertexInputAttributeDescription *vi_attrib, int count) { 1196 m_vi_state.pVertexAttributeDescriptions = vi_attrib; 1197 m_vi_state.vertexAttributeDescriptionCount = count; 1198 } 1199 1200 void VkPipelineObj::AddVertexInputBindings( 1201 VkVertexInputBindingDescription *vi_binding, int count) { 1202 m_vi_state.pVertexBindingDescriptions = vi_binding; 1203 m_vi_state.vertexBindingDescriptionCount = count; 1204 } 1205 1206 void VkPipelineObj::AddColorAttachment( 1207 uint32_t binding, const VkPipelineColorBlendAttachmentState *att) { 1208 if (binding + 1 > m_colorAttachments.size()) { 1209 m_colorAttachments.resize(binding + 1); 1210 } 1211 m_colorAttachments[binding] = *att; 1212 } 1213 1214 void VkPipelineObj::SetDepthStencil( 1215 VkPipelineDepthStencilStateCreateInfo *ds_state) { 1216 m_ds_state.depthTestEnable = ds_state->depthTestEnable; 1217 m_ds_state.depthWriteEnable = ds_state->depthWriteEnable; 1218 m_ds_state.depthBoundsTestEnable = ds_state->depthBoundsTestEnable; 1219 m_ds_state.depthCompareOp = ds_state->depthCompareOp; 1220 m_ds_state.stencilTestEnable = ds_state->stencilTestEnable; 1221 m_ds_state.back = ds_state->back; 1222 m_ds_state.front = ds_state->front; 1223 } 1224 1225 void VkPipelineObj::SetViewport(vector<VkViewport> viewports) { 1226 m_viewports = viewports; 1227 // If we explicitly set a null viewport, pass it through to create info 1228 // but preserve viewportCount because it musn't change 1229 if (m_viewports.size() == 0) { 1230 m_vp_state.pViewports = nullptr; 1231 } 1232 } 1233 1234 void VkPipelineObj::SetScissor(vector<VkRect2D> scissors) { 1235 m_scissors = scissors; 1236 // If we explicitly set a null scissors, pass it through to create info 1237 // but preserve viewportCount because it musn't change 1238 if (m_scissors.size() == 0) { 1239 m_vp_state.pScissors = nullptr; 1240 } 1241 } 1242 1243 void VkPipelineObj::MakeDynamic(VkDynamicState state) { 1244 /* Only add a state once */ 1245 for (auto it = m_dynamic_state_enables.begin(); 1246 it != m_dynamic_state_enables.end(); it++) { 1247 if ((*it) == state) 1248 return; 1249 } 1250 m_dynamic_state_enables.push_back(state); 1251 } 1252 1253 void VkPipelineObj::SetMSAA(VkPipelineMultisampleStateCreateInfo *ms_state) { 1254 memcpy(&m_ms_state, ms_state, sizeof(VkPipelineMultisampleStateCreateInfo)); 1255 } 1256 1257 VkResult VkPipelineObj::CreateVKPipeline(VkPipelineLayout layout, 1258 VkRenderPass render_pass) { 1259 VkGraphicsPipelineCreateInfo info = {}; 1260 VkPipelineDynamicStateCreateInfo dsci = {}; 1261 1262 info.stageCount = m_shaderObjs.size(); 1263 info.pStages = new VkPipelineShaderStageCreateInfo[info.stageCount]; 1264 1265 for (size_t i = 0; i < m_shaderObjs.size(); i++) { 1266 ((VkPipelineShaderStageCreateInfo *)info.pStages)[i] = 1267 m_shaderObjs[i]->GetStageCreateInfo(); 1268 } 1269 1270 if (m_vi_state.vertexAttributeDescriptionCount && 1271 m_vi_state.vertexBindingDescriptionCount) { 1272 m_vi_state.sType = 1273 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 1274 info.pVertexInputState = &m_vi_state; 1275 } else { 1276 info.pVertexInputState = NULL; 1277 } 1278 1279 info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 1280 info.pNext = NULL; 1281 info.flags = 0; 1282 info.layout = layout; 1283 1284 m_cb_state.attachmentCount = m_colorAttachments.size(); 1285 m_cb_state.pAttachments = m_colorAttachments.data(); 1286 1287 if (m_viewports.size() > 0) { 1288 m_vp_state.viewportCount = m_viewports.size(); 1289 m_vp_state.pViewports = m_viewports.data(); 1290 } else { 1291 MakeDynamic(VK_DYNAMIC_STATE_VIEWPORT); 1292 } 1293 1294 if (m_scissors.size() > 0) { 1295 m_vp_state.scissorCount = m_scissors.size(); 1296 m_vp_state.pScissors = m_scissors.data(); 1297 } else { 1298 MakeDynamic(VK_DYNAMIC_STATE_SCISSOR); 1299 } 1300 1301 if (m_dynamic_state_enables.size() > 0) { 1302 dsci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 1303 dsci.dynamicStateCount = m_dynamic_state_enables.size(); 1304 dsci.pDynamicStates = m_dynamic_state_enables.data(); 1305 info.pDynamicState = &dsci; 1306 } 1307 1308 info.renderPass = render_pass; 1309 info.subpass = 0; 1310 info.pTessellationState = NULL; 1311 info.pInputAssemblyState = &m_ia_state; 1312 info.pViewportState = &m_vp_state; 1313 info.pRasterizationState = &m_rs_state; 1314 info.pMultisampleState = &m_ms_state; 1315 info.pDepthStencilState = &m_ds_state; 1316 info.pColorBlendState = &m_cb_state; 1317 1318 return init_try(*m_device, info); 1319 } 1320 1321 VkCommandBufferObj::VkCommandBufferObj(VkDeviceObj *device, 1322 VkCommandPool pool) { 1323 m_device = device; 1324 1325 init(*device, vk_testing::CommandBuffer::create_info(pool)); 1326 } 1327 1328 VkCommandBuffer VkCommandBufferObj::GetBufferHandle() { return handle(); } 1329 1330 VkResult 1331 VkCommandBufferObj::BeginCommandBuffer(VkCommandBufferBeginInfo *pInfo) { 1332 begin(pInfo); 1333 return VK_SUCCESS; 1334 } 1335 1336 VkResult VkCommandBufferObj::BeginCommandBuffer() { 1337 begin(); 1338 return VK_SUCCESS; 1339 } 1340 1341 VkResult VkCommandBufferObj::EndCommandBuffer() { 1342 end(); 1343 return VK_SUCCESS; 1344 } 1345 1346 void VkCommandBufferObj::PipelineBarrier( 1347 VkPipelineStageFlags src_stages, VkPipelineStageFlags dest_stages, 1348 VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, 1349 const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, 1350 const VkBufferMemoryBarrier *pBufferMemoryBarriers, 1351 uint32_t imageMemoryBarrierCount, 1352 const VkImageMemoryBarrier *pImageMemoryBarriers) { 1353 vkCmdPipelineBarrier(handle(), src_stages, dest_stages, dependencyFlags, 1354 memoryBarrierCount, pMemoryBarriers, 1355 bufferMemoryBarrierCount, pBufferMemoryBarriers, 1356 imageMemoryBarrierCount, pImageMemoryBarriers); 1357 } 1358 1359 void VkCommandBufferObj::ClearAllBuffers(VkClearColorValue clear_color, 1360 float depth_clear_color, 1361 uint32_t stencil_clear_color, 1362 VkDepthStencilObj *depthStencilObj) { 1363 uint32_t i; 1364 const VkFlags output_mask = VK_ACCESS_HOST_WRITE_BIT | 1365 VK_ACCESS_SHADER_WRITE_BIT | 1366 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 1367 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 1368 VK_ACCESS_TRANSFER_WRITE_BIT; 1369 const VkFlags input_mask = 0; 1370 1371 // whatever we want to do, we do it to the whole buffer 1372 VkImageSubresourceRange srRange = {}; 1373 srRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1374 srRange.baseMipLevel = 0; 1375 srRange.levelCount = VK_REMAINING_MIP_LEVELS; 1376 srRange.baseArrayLayer = 0; 1377 srRange.layerCount = VK_REMAINING_ARRAY_LAYERS; 1378 1379 VkImageMemoryBarrier memory_barrier = {}; 1380 memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 1381 memory_barrier.srcAccessMask = output_mask; 1382 memory_barrier.dstAccessMask = input_mask; 1383 memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; 1384 memory_barrier.subresourceRange = srRange; 1385 VkImageMemoryBarrier *pmemory_barrier = &memory_barrier; 1386 1387 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 1388 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 1389 1390 for (i = 0; i < m_renderTargets.size(); i++) { 1391 memory_barrier.image = m_renderTargets[i]->image(); 1392 memory_barrier.oldLayout = m_renderTargets[i]->layout(); 1393 vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, 1394 NULL, 1, pmemory_barrier); 1395 m_renderTargets[i]->layout(memory_barrier.newLayout); 1396 1397 vkCmdClearColorImage(handle(), m_renderTargets[i]->image(), 1398 VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, 1399 &srRange); 1400 } 1401 1402 if (depthStencilObj) { 1403 VkImageSubresourceRange dsRange = {}; 1404 dsRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; 1405 dsRange.baseMipLevel = 0; 1406 dsRange.levelCount = VK_REMAINING_MIP_LEVELS; 1407 dsRange.baseArrayLayer = 0; 1408 dsRange.layerCount = VK_REMAINING_ARRAY_LAYERS; 1409 1410 // prepare the depth buffer for clear 1411 1412 memory_barrier.oldLayout = memory_barrier.newLayout; 1413 memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; 1414 memory_barrier.image = depthStencilObj->handle(); 1415 memory_barrier.subresourceRange = dsRange; 1416 1417 vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, 1418 NULL, 1, pmemory_barrier); 1419 1420 VkClearDepthStencilValue clear_value = {depth_clear_color, 1421 stencil_clear_color}; 1422 vkCmdClearDepthStencilImage(handle(), depthStencilObj->handle(), 1423 VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, 1424 &dsRange); 1425 1426 // prepare depth buffer for rendering 1427 memory_barrier.image = depthStencilObj->handle(); 1428 memory_barrier.newLayout = memory_barrier.oldLayout; 1429 memory_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; 1430 memory_barrier.subresourceRange = dsRange; 1431 vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, 1432 NULL, 1, pmemory_barrier); 1433 } 1434 } 1435 1436 void VkCommandBufferObj::FillBuffer(VkBuffer buffer, VkDeviceSize offset, 1437 VkDeviceSize fill_size, uint32_t data) { 1438 vkCmdFillBuffer(handle(), buffer, offset, fill_size, data); 1439 } 1440 1441 void VkCommandBufferObj::UpdateBuffer(VkBuffer buffer, VkDeviceSize dstOffset, 1442 VkDeviceSize dataSize, 1443 const uint32_t *pData) { 1444 vkCmdUpdateBuffer(handle(), buffer, dstOffset, dataSize, pData); 1445 } 1446 1447 void VkCommandBufferObj::CopyImage(VkImage srcImage, 1448 VkImageLayout srcImageLayout, 1449 VkImage dstImage, 1450 VkImageLayout dstImageLayout, 1451 uint32_t regionCount, 1452 const VkImageCopy *pRegions) { 1453 vkCmdCopyImage(handle(), srcImage, srcImageLayout, dstImage, dstImageLayout, 1454 regionCount, pRegions); 1455 } 1456 1457 void VkCommandBufferObj::ResolveImage(VkImage srcImage, 1458 VkImageLayout srcImageLayout, 1459 VkImage dstImage, 1460 VkImageLayout dstImageLayout, 1461 uint32_t regionCount, 1462 const VkImageResolve *pRegions) { 1463 vkCmdResolveImage(handle(), srcImage, srcImageLayout, dstImage, 1464 dstImageLayout, regionCount, pRegions); 1465 } 1466 1467 void VkCommandBufferObj::PrepareAttachments() { 1468 uint32_t i; 1469 const VkFlags output_mask = VK_ACCESS_HOST_WRITE_BIT | 1470 VK_ACCESS_SHADER_WRITE_BIT | 1471 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 1472 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 1473 VK_ACCESS_TRANSFER_WRITE_BIT; 1474 const VkFlags input_mask = 1475 VK_ACCESS_HOST_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT | 1476 VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | 1477 VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT | 1478 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 1479 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_MEMORY_READ_BIT; 1480 1481 VkImageSubresourceRange srRange = {}; 1482 srRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1483 srRange.baseMipLevel = 0; 1484 srRange.levelCount = VK_REMAINING_MIP_LEVELS; 1485 srRange.baseArrayLayer = 0; 1486 srRange.layerCount = VK_REMAINING_ARRAY_LAYERS; 1487 1488 VkImageMemoryBarrier memory_barrier = {}; 1489 memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 1490 memory_barrier.srcAccessMask = output_mask; 1491 memory_barrier.dstAccessMask = input_mask; 1492 memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1493 memory_barrier.subresourceRange = srRange; 1494 VkImageMemoryBarrier *pmemory_barrier = &memory_barrier; 1495 1496 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 1497 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 1498 1499 for (i = 0; i < m_renderTargets.size(); i++) { 1500 memory_barrier.image = m_renderTargets[i]->image(); 1501 memory_barrier.oldLayout = m_renderTargets[i]->layout(); 1502 vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, 1503 NULL, 1, pmemory_barrier); 1504 m_renderTargets[i]->layout(memory_barrier.newLayout); 1505 } 1506 } 1507 1508 void VkCommandBufferObj::BeginRenderPass(const VkRenderPassBeginInfo &info) { 1509 vkCmdBeginRenderPass(handle(), &info, VK_SUBPASS_CONTENTS_INLINE); 1510 } 1511 1512 void VkCommandBufferObj::EndRenderPass() { vkCmdEndRenderPass(handle()); } 1513 1514 void VkCommandBufferObj::SetViewport(uint32_t firstViewport, 1515 uint32_t viewportCount, 1516 const VkViewport *pViewports) { 1517 vkCmdSetViewport(handle(), firstViewport, viewportCount, pViewports); 1518 } 1519 1520 void VkCommandBufferObj::SetScissor(uint32_t firstScissor, 1521 uint32_t scissorCount, 1522 const VkRect2D *pScissors) { 1523 vkCmdSetScissor(handle(), firstScissor, scissorCount, pScissors); 1524 } 1525 1526 void VkCommandBufferObj::SetLineWidth(float lineWidth) { 1527 vkCmdSetLineWidth(handle(), lineWidth); 1528 } 1529 1530 void VkCommandBufferObj::SetDepthBias(float depthBiasConstantFactor, 1531 float depthBiasClamp, 1532 float depthBiasSlopeFactor) { 1533 vkCmdSetDepthBias(handle(), depthBiasConstantFactor, depthBiasClamp, 1534 depthBiasSlopeFactor); 1535 } 1536 1537 void VkCommandBufferObj::SetBlendConstants(const float blendConstants[4]) { 1538 vkCmdSetBlendConstants(handle(), blendConstants); 1539 } 1540 1541 void VkCommandBufferObj::SetDepthBounds(float minDepthBounds, 1542 float maxDepthBounds) { 1543 vkCmdSetDepthBounds(handle(), minDepthBounds, maxDepthBounds); 1544 } 1545 1546 void VkCommandBufferObj::SetStencilReadMask(VkStencilFaceFlags faceMask, 1547 uint32_t compareMask) { 1548 vkCmdSetStencilCompareMask(handle(), faceMask, compareMask); 1549 } 1550 1551 void VkCommandBufferObj::SetStencilWriteMask(VkStencilFaceFlags faceMask, 1552 uint32_t writeMask) { 1553 vkCmdSetStencilWriteMask(handle(), faceMask, writeMask); 1554 } 1555 1556 void VkCommandBufferObj::SetStencilReference(VkStencilFaceFlags faceMask, 1557 uint32_t reference) { 1558 vkCmdSetStencilReference(handle(), faceMask, reference); 1559 } 1560 1561 void VkCommandBufferObj::AddRenderTarget(VkImageObj *renderTarget) { 1562 m_renderTargets.push_back(renderTarget); 1563 } 1564 1565 void VkCommandBufferObj::DrawIndexed(uint32_t indexCount, 1566 uint32_t instanceCount, 1567 uint32_t firstIndex, int32_t vertexOffset, 1568 uint32_t firstInstance) { 1569 vkCmdDrawIndexed(handle(), indexCount, instanceCount, firstIndex, 1570 vertexOffset, firstInstance); 1571 } 1572 1573 void VkCommandBufferObj::Draw(uint32_t vertexCount, uint32_t instanceCount, 1574 uint32_t firstVertex, uint32_t firstInstance) { 1575 vkCmdDraw(handle(), vertexCount, instanceCount, firstVertex, firstInstance); 1576 } 1577 1578 void VkCommandBufferObj::QueueCommandBuffer() { 1579 VkFence nullFence = {VK_NULL_HANDLE}; 1580 QueueCommandBuffer(nullFence); 1581 } 1582 1583 void VkCommandBufferObj::QueueCommandBuffer(VkFence fence) { 1584 VkResult err = VK_SUCCESS; 1585 1586 // submit the command buffer to the universal queue 1587 VkSubmitInfo submit_info; 1588 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 1589 submit_info.pNext = NULL; 1590 submit_info.waitSemaphoreCount = 0; 1591 submit_info.pWaitSemaphores = NULL; 1592 submit_info.pWaitDstStageMask = NULL; 1593 submit_info.commandBufferCount = 1; 1594 submit_info.pCommandBuffers = &handle(); 1595 submit_info.signalSemaphoreCount = 0; 1596 submit_info.pSignalSemaphores = NULL; 1597 1598 err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence); 1599 ASSERT_VK_SUCCESS(err); 1600 1601 err = vkQueueWaitIdle(m_device->m_queue); 1602 ASSERT_VK_SUCCESS(err); 1603 1604 // Wait for work to finish before cleaning up. 1605 vkDeviceWaitIdle(m_device->device()); 1606 } 1607 1608 void VkCommandBufferObj::BindPipeline(VkPipelineObj &pipeline) { 1609 vkCmdBindPipeline(handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, 1610 pipeline.handle()); 1611 } 1612 1613 void VkCommandBufferObj::BindDescriptorSet(VkDescriptorSetObj &descriptorSet) { 1614 VkDescriptorSet set_obj = descriptorSet.GetDescriptorSetHandle(); 1615 1616 // bind pipeline, vertex buffer (descriptor set) and WVP (dynamic buffer 1617 // view) 1618 vkCmdBindDescriptorSets(handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, 1619 descriptorSet.GetPipelineLayout(), 0, 1, &set_obj, 1620 0, NULL); 1621 } 1622 1623 void VkCommandBufferObj::BindIndexBuffer(VkIndexBufferObj *indexBuffer, 1624 VkDeviceSize offset) { 1625 vkCmdBindIndexBuffer(handle(), indexBuffer->handle(), offset, 1626 indexBuffer->GetIndexType()); 1627 } 1628 1629 void VkCommandBufferObj::BindVertexBuffer(VkConstantBufferObj *vertexBuffer, 1630 VkDeviceSize offset, 1631 uint32_t binding) { 1632 vkCmdBindVertexBuffers(handle(), binding, 1, &vertexBuffer->handle(), 1633 &offset); 1634 } 1635 1636 VkDepthStencilObj::VkDepthStencilObj() { m_initialized = false; } 1637 bool VkDepthStencilObj::Initialized() { return m_initialized; } 1638 1639 VkImageView *VkDepthStencilObj::BindInfo() { return &m_attachmentBindInfo; } 1640 1641 void VkDepthStencilObj::Init(VkDeviceObj *device, int32_t width, int32_t height, 1642 VkFormat format) { 1643 VkImageCreateInfo image_info = {}; 1644 VkImageViewCreateInfo view_info = {}; 1645 1646 m_device = device; 1647 m_initialized = true; 1648 m_depth_stencil_fmt = format; 1649 1650 image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 1651 image_info.pNext = NULL; 1652 image_info.imageType = VK_IMAGE_TYPE_2D; 1653 image_info.format = m_depth_stencil_fmt; 1654 image_info.extent.width = width; 1655 image_info.extent.height = height; 1656 image_info.extent.depth = 1; 1657 image_info.mipLevels = 1; 1658 image_info.arrayLayers = 1; 1659 image_info.samples = VK_SAMPLE_COUNT_1_BIT; 1660 image_info.tiling = VK_IMAGE_TILING_OPTIMAL; 1661 image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 1662 image_info.flags = 0; 1663 image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 1664 image_info.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 1665 image_info.queueFamilyIndexCount = 0; 1666 image_info.pQueueFamilyIndices = NULL; 1667 init(*m_device, image_info); 1668 1669 view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 1670 view_info.pNext = NULL; 1671 view_info.image = VK_NULL_HANDLE; 1672 view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; 1673 view_info.subresourceRange.baseMipLevel = 0; 1674 view_info.subresourceRange.levelCount = 1; 1675 view_info.subresourceRange.baseArrayLayer = 0; 1676 view_info.subresourceRange.layerCount = 1; 1677 view_info.flags = 0; 1678 view_info.format = m_depth_stencil_fmt; 1679 view_info.image = handle(); 1680 view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 1681 m_imageView.init(*m_device, view_info); 1682 1683 m_attachmentBindInfo = m_imageView.handle(); 1684 } 1685