vulkan_builders.cpp (34595B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #include "vulkan_builders.h" 5 6 #include "common/assert.h" 7 #include "common/error.h" 8 #include "common/log.h" 9 10 #include <limits> 11 12 void Vulkan::AddPointerToChain(void* head, const void* ptr) 13 { 14 VkBaseInStructure* last_st = static_cast<VkBaseInStructure*>(head); 15 while (last_st->pNext) 16 { 17 if (last_st->pNext == ptr) 18 return; 19 20 last_st = const_cast<VkBaseInStructure*>(last_st->pNext); 21 } 22 23 last_st->pNext = static_cast<const VkBaseInStructure*>(ptr); 24 } 25 26 const char* Vulkan::VkResultToString(VkResult res) 27 { 28 switch (res) 29 { 30 case VK_SUCCESS: 31 return "VK_SUCCESS"; 32 33 case VK_NOT_READY: 34 return "VK_NOT_READY"; 35 36 case VK_TIMEOUT: 37 return "VK_TIMEOUT"; 38 39 case VK_EVENT_SET: 40 return "VK_EVENT_SET"; 41 42 case VK_EVENT_RESET: 43 return "VK_EVENT_RESET"; 44 45 case VK_INCOMPLETE: 46 return "VK_INCOMPLETE"; 47 48 case VK_ERROR_OUT_OF_HOST_MEMORY: 49 return "VK_ERROR_OUT_OF_HOST_MEMORY"; 50 51 case VK_ERROR_OUT_OF_DEVICE_MEMORY: 52 return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; 53 54 case VK_ERROR_INITIALIZATION_FAILED: 55 return "VK_ERROR_INITIALIZATION_FAILED"; 56 57 case VK_ERROR_DEVICE_LOST: 58 return "VK_ERROR_DEVICE_LOST"; 59 60 case VK_ERROR_MEMORY_MAP_FAILED: 61 return "VK_ERROR_MEMORY_MAP_FAILED"; 62 63 case VK_ERROR_LAYER_NOT_PRESENT: 64 return "VK_ERROR_LAYER_NOT_PRESENT"; 65 66 case VK_ERROR_EXTENSION_NOT_PRESENT: 67 return "VK_ERROR_EXTENSION_NOT_PRESENT"; 68 69 case VK_ERROR_FEATURE_NOT_PRESENT: 70 return "VK_ERROR_FEATURE_NOT_PRESENT"; 71 72 case VK_ERROR_INCOMPATIBLE_DRIVER: 73 return "VK_ERROR_INCOMPATIBLE_DRIVER"; 74 75 case VK_ERROR_TOO_MANY_OBJECTS: 76 return "VK_ERROR_TOO_MANY_OBJECTS"; 77 78 case VK_ERROR_FORMAT_NOT_SUPPORTED: 79 return "VK_ERROR_FORMAT_NOT_SUPPORTED"; 80 81 case VK_ERROR_SURFACE_LOST_KHR: 82 return "VK_ERROR_SURFACE_LOST_KHR"; 83 84 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: 85 return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; 86 87 case VK_SUBOPTIMAL_KHR: 88 return "VK_SUBOPTIMAL_KHR"; 89 90 case VK_ERROR_OUT_OF_DATE_KHR: 91 return "VK_ERROR_OUT_OF_DATE_KHR"; 92 93 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: 94 return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; 95 96 case VK_ERROR_VALIDATION_FAILED_EXT: 97 return "VK_ERROR_VALIDATION_FAILED_EXT"; 98 99 case VK_ERROR_INVALID_SHADER_NV: 100 return "VK_ERROR_INVALID_SHADER_NV"; 101 102 default: 103 return "UNKNOWN_VK_RESULT"; 104 } 105 } 106 107 void Vulkan::LogVulkanResult(const char* func_name, VkResult res, std::string_view msg) 108 { 109 Log::FastWrite("VulkanDevice", func_name, LOGLEVEL_ERROR, "{} (0x{:08X}: {})", msg, static_cast<unsigned>(res), 110 VkResultToString(res)); 111 } 112 113 void Vulkan::SetErrorObject(Error* errptr, std::string_view prefix, VkResult res) 114 { 115 Error::SetStringFmt(errptr, "{} (0x{:08X}: {})", prefix, static_cast<unsigned>(res), VkResultToString(res)); 116 } 117 118 Vulkan::DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder() 119 { 120 Clear(); 121 } 122 123 void Vulkan::DescriptorSetLayoutBuilder::Clear() 124 { 125 m_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 126 m_ci.pNext = nullptr; 127 m_ci.flags = 0; 128 m_ci.pBindings = nullptr; 129 m_ci.bindingCount = 0; 130 } 131 132 void Vulkan::DescriptorSetLayoutBuilder::SetPushFlag() 133 { 134 m_ci.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 135 } 136 137 VkDescriptorSetLayout Vulkan::DescriptorSetLayoutBuilder::Create(VkDevice device) 138 { 139 VkDescriptorSetLayout layout; 140 VkResult res = vkCreateDescriptorSetLayout(device, &m_ci, nullptr, &layout); 141 if (res != VK_SUCCESS) 142 { 143 LOG_VULKAN_ERROR(res, "vkCreateDescriptorSetLayout() failed: "); 144 return VK_NULL_HANDLE; 145 } 146 147 Clear(); 148 return layout; 149 } 150 151 void Vulkan::DescriptorSetLayoutBuilder::AddBinding(u32 binding, VkDescriptorType dtype, u32 dcount, 152 VkShaderStageFlags stages) 153 { 154 DebugAssert(m_ci.bindingCount < MAX_BINDINGS); 155 156 VkDescriptorSetLayoutBinding& b = m_bindings[m_ci.bindingCount]; 157 b.binding = binding; 158 b.descriptorType = dtype; 159 b.descriptorCount = dcount; 160 b.stageFlags = stages; 161 b.pImmutableSamplers = nullptr; 162 163 m_ci.pBindings = m_bindings.data(); 164 m_ci.bindingCount++; 165 } 166 167 Vulkan::PipelineLayoutBuilder::PipelineLayoutBuilder() 168 { 169 Clear(); 170 } 171 172 void Vulkan::PipelineLayoutBuilder::Clear() 173 { 174 m_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 175 m_ci.pNext = nullptr; 176 m_ci.flags = 0; 177 m_ci.pSetLayouts = nullptr; 178 m_ci.setLayoutCount = 0; 179 m_ci.pPushConstantRanges = nullptr; 180 m_ci.pushConstantRangeCount = 0; 181 } 182 183 VkPipelineLayout Vulkan::PipelineLayoutBuilder::Create(VkDevice device) 184 { 185 VkPipelineLayout layout; 186 VkResult res = vkCreatePipelineLayout(device, &m_ci, nullptr, &layout); 187 if (res != VK_SUCCESS) 188 { 189 LOG_VULKAN_ERROR(res, "vkCreatePipelineLayout() failed: "); 190 return VK_NULL_HANDLE; 191 } 192 193 Clear(); 194 return layout; 195 } 196 197 void Vulkan::PipelineLayoutBuilder::AddDescriptorSet(VkDescriptorSetLayout layout) 198 { 199 DebugAssert(m_ci.setLayoutCount < MAX_SETS); 200 201 m_sets[m_ci.setLayoutCount] = layout; 202 203 m_ci.setLayoutCount++; 204 m_ci.pSetLayouts = m_sets.data(); 205 } 206 207 void Vulkan::PipelineLayoutBuilder::AddPushConstants(VkShaderStageFlags stages, u32 offset, u32 size) 208 { 209 DebugAssert(m_ci.pushConstantRangeCount < MAX_PUSH_CONSTANTS); 210 211 VkPushConstantRange& r = m_push_constants[m_ci.pushConstantRangeCount]; 212 r.stageFlags = stages; 213 r.offset = offset; 214 r.size = size; 215 216 m_ci.pushConstantRangeCount++; 217 m_ci.pPushConstantRanges = m_push_constants.data(); 218 } 219 220 Vulkan::GraphicsPipelineBuilder::GraphicsPipelineBuilder() 221 { 222 Clear(); 223 } 224 225 void Vulkan::GraphicsPipelineBuilder::Clear() 226 { 227 m_ci = {}; 228 m_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 229 230 m_shader_stages = {}; 231 232 m_vertex_input_state = {}; 233 m_vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 234 m_ci.pVertexInputState = &m_vertex_input_state; 235 m_vertex_attributes = {}; 236 m_vertex_buffers = {}; 237 238 m_input_assembly = {}; 239 m_input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 240 241 m_rasterization_state = {}; 242 m_rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 243 m_rasterization_state.lineWidth = 1.0f; 244 m_depth_state = {}; 245 m_depth_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 246 m_blend_state = {}; 247 m_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 248 m_blend_attachments = {}; 249 250 m_viewport_state = {}; 251 m_viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 252 m_viewport = {}; 253 m_scissor = {}; 254 255 m_dynamic_state = {}; 256 m_dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 257 m_dynamic_state_values = {}; 258 259 m_multisample_state = {}; 260 m_multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 261 262 m_provoking_vertex = {}; 263 m_provoking_vertex.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT; 264 265 m_line_rasterization_state = {}; 266 m_line_rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT; 267 268 m_rendering = {}; 269 m_rendering.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; 270 271 m_rendering_input_attachment_locations = {}; 272 m_rendering_input_attachment_locations.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR; 273 274 // set defaults 275 SetNoCullRasterizationState(); 276 SetNoDepthTestState(); 277 SetNoBlendingState(); 278 SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); 279 280 // have to be specified even if dynamic 281 SetViewport(0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f); 282 SetScissorRect(0, 0, 1, 1); 283 SetMultisamples(VK_SAMPLE_COUNT_1_BIT); 284 } 285 286 VkPipeline Vulkan::GraphicsPipelineBuilder::Create(VkDevice device, VkPipelineCache pipeline_cache, bool clear, 287 Error* error) 288 { 289 VkPipeline pipeline; 290 VkResult res = vkCreateGraphicsPipelines(device, pipeline_cache, 1, &m_ci, nullptr, &pipeline); 291 if (res != VK_SUCCESS) 292 { 293 LOG_VULKAN_ERROR(res, "vkCreateGraphicsPipelines() failed: "); 294 SetErrorObject(error, "vkCreateGraphicsPipelines() failed: ", res); 295 return VK_NULL_HANDLE; 296 } 297 298 if (clear) 299 Clear(); 300 301 return pipeline; 302 } 303 304 void Vulkan::GraphicsPipelineBuilder::SetShaderStage(VkShaderStageFlagBits stage, VkShaderModule module, 305 const char* entry_point) 306 { 307 DebugAssert(m_ci.stageCount < MAX_SHADER_STAGES); 308 309 u32 index = 0; 310 for (; index < m_ci.stageCount; index++) 311 { 312 if (m_shader_stages[index].stage == stage) 313 break; 314 } 315 if (index == m_ci.stageCount) 316 { 317 m_ci.stageCount++; 318 m_ci.pStages = m_shader_stages.data(); 319 } 320 321 VkPipelineShaderStageCreateInfo& s = m_shader_stages[index]; 322 s.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 323 s.stage = stage; 324 s.module = module; 325 s.pName = entry_point; 326 } 327 328 void Vulkan::GraphicsPipelineBuilder::AddVertexBuffer(u32 binding, u32 stride, 329 VkVertexInputRate input_rate /*= VK_VERTEX_INPUT_RATE_VERTEX*/) 330 { 331 DebugAssert(m_vertex_input_state.vertexAttributeDescriptionCount < MAX_VERTEX_BUFFERS); 332 333 VkVertexInputBindingDescription& b = m_vertex_buffers[m_vertex_input_state.vertexBindingDescriptionCount]; 334 b.binding = binding; 335 b.stride = stride; 336 b.inputRate = input_rate; 337 338 m_vertex_input_state.vertexBindingDescriptionCount++; 339 m_vertex_input_state.pVertexBindingDescriptions = m_vertex_buffers.data(); 340 m_ci.pVertexInputState = &m_vertex_input_state; 341 } 342 343 void Vulkan::GraphicsPipelineBuilder::AddVertexAttribute(u32 location, u32 binding, VkFormat format, u32 offset) 344 { 345 DebugAssert(m_vertex_input_state.vertexAttributeDescriptionCount < MAX_VERTEX_BUFFERS); 346 347 VkVertexInputAttributeDescription& a = m_vertex_attributes[m_vertex_input_state.vertexAttributeDescriptionCount]; 348 a.location = location; 349 a.binding = binding; 350 a.format = format; 351 a.offset = offset; 352 353 m_vertex_input_state.vertexAttributeDescriptionCount++; 354 m_vertex_input_state.pVertexAttributeDescriptions = m_vertex_attributes.data(); 355 m_ci.pVertexInputState = &m_vertex_input_state; 356 } 357 358 void Vulkan::GraphicsPipelineBuilder::SetPrimitiveTopology(VkPrimitiveTopology topology, 359 bool enable_primitive_restart /*= false*/) 360 { 361 m_input_assembly.topology = topology; 362 m_input_assembly.primitiveRestartEnable = enable_primitive_restart; 363 364 m_ci.pInputAssemblyState = &m_input_assembly; 365 } 366 367 void Vulkan::GraphicsPipelineBuilder::SetRasterizationState(VkPolygonMode polygon_mode, VkCullModeFlags cull_mode, 368 VkFrontFace front_face) 369 { 370 m_rasterization_state.polygonMode = polygon_mode; 371 m_rasterization_state.cullMode = cull_mode; 372 m_rasterization_state.frontFace = front_face; 373 374 m_ci.pRasterizationState = &m_rasterization_state; 375 } 376 377 void Vulkan::GraphicsPipelineBuilder::SetLineWidth(float width) 378 { 379 m_rasterization_state.lineWidth = width; 380 } 381 382 void Vulkan::GraphicsPipelineBuilder::SetLineRasterizationMode(VkLineRasterizationModeEXT mode) 383 { 384 AddPointerToChain(&m_rasterization_state, &m_line_rasterization_state); 385 386 m_line_rasterization_state.lineRasterizationMode = mode; 387 } 388 389 void Vulkan::GraphicsPipelineBuilder::SetMultisamples(u32 multisamples, bool per_sample_shading) 390 { 391 m_multisample_state.rasterizationSamples = static_cast<VkSampleCountFlagBits>(multisamples); 392 m_multisample_state.sampleShadingEnable = per_sample_shading; 393 m_multisample_state.minSampleShading = (multisamples > 1) ? 1.0f : 0.0f; 394 m_ci.pMultisampleState = &m_multisample_state; 395 } 396 397 void Vulkan::GraphicsPipelineBuilder::SetMultisamples(VkSampleCountFlagBits samples) 398 { 399 m_multisample_state.rasterizationSamples = samples; 400 m_ci.pMultisampleState = &m_multisample_state; 401 } 402 403 void Vulkan::GraphicsPipelineBuilder::SetNoCullRasterizationState() 404 { 405 SetRasterizationState(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE); 406 } 407 408 void Vulkan::GraphicsPipelineBuilder::SetDepthState(bool depth_test, bool depth_write, VkCompareOp compare_op) 409 { 410 m_depth_state.depthTestEnable = depth_test; 411 m_depth_state.depthWriteEnable = depth_write; 412 m_depth_state.depthCompareOp = compare_op; 413 414 m_ci.pDepthStencilState = &m_depth_state; 415 } 416 417 void Vulkan::GraphicsPipelineBuilder::SetStencilState(bool stencil_test, const VkStencilOpState& front, 418 const VkStencilOpState& back) 419 { 420 m_depth_state.stencilTestEnable = stencil_test; 421 m_depth_state.front = front; 422 m_depth_state.back = back; 423 } 424 425 void Vulkan::GraphicsPipelineBuilder::SetNoStencilState() 426 { 427 m_depth_state.stencilTestEnable = VK_FALSE; 428 m_depth_state.front = {}; 429 m_depth_state.back = {}; 430 } 431 432 void Vulkan::GraphicsPipelineBuilder::SetNoDepthTestState() 433 { 434 SetDepthState(false, false, VK_COMPARE_OP_ALWAYS); 435 } 436 437 void Vulkan::GraphicsPipelineBuilder::SetBlendConstants(float r, float g, float b, float a) 438 { 439 m_blend_state.blendConstants[0] = r; 440 m_blend_state.blendConstants[1] = g; 441 m_blend_state.blendConstants[2] = b; 442 m_blend_state.blendConstants[3] = a; 443 m_ci.pColorBlendState = &m_blend_state; 444 } 445 446 void Vulkan::GraphicsPipelineBuilder::AddBlendAttachment( 447 bool blend_enable, VkBlendFactor src_factor, VkBlendFactor dst_factor, VkBlendOp op, 448 VkBlendFactor alpha_src_factor, VkBlendFactor alpha_dst_factor, VkBlendOp alpha_op, VkColorComponentFlags write_mask /* = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT */) 449 { 450 DebugAssert(m_blend_state.attachmentCount < MAX_ATTACHMENTS); 451 452 VkPipelineColorBlendAttachmentState& bs = m_blend_attachments[m_blend_state.attachmentCount]; 453 bs.blendEnable = blend_enable; 454 bs.srcColorBlendFactor = src_factor; 455 bs.dstColorBlendFactor = dst_factor; 456 bs.colorBlendOp = op; 457 bs.srcAlphaBlendFactor = alpha_src_factor; 458 bs.dstAlphaBlendFactor = alpha_dst_factor; 459 bs.alphaBlendOp = alpha_op; 460 bs.colorWriteMask = write_mask; 461 462 m_blend_state.attachmentCount++; 463 m_blend_state.pAttachments = m_blend_attachments.data(); 464 m_ci.pColorBlendState = &m_blend_state; 465 } 466 467 void Vulkan::GraphicsPipelineBuilder::SetBlendAttachment( 468 u32 attachment, bool blend_enable, VkBlendFactor src_factor, VkBlendFactor dst_factor, VkBlendOp op, 469 VkBlendFactor alpha_src_factor, VkBlendFactor alpha_dst_factor, VkBlendOp alpha_op, VkColorComponentFlags write_mask /*= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT*/) 470 { 471 DebugAssert(attachment < MAX_ATTACHMENTS); 472 473 VkPipelineColorBlendAttachmentState& bs = m_blend_attachments[attachment]; 474 bs.blendEnable = blend_enable; 475 bs.srcColorBlendFactor = src_factor; 476 bs.dstColorBlendFactor = dst_factor; 477 bs.colorBlendOp = op; 478 bs.srcAlphaBlendFactor = alpha_src_factor; 479 bs.dstAlphaBlendFactor = alpha_dst_factor; 480 bs.alphaBlendOp = alpha_op; 481 bs.colorWriteMask = write_mask; 482 483 if (attachment >= m_blend_state.attachmentCount) 484 { 485 m_blend_state.attachmentCount = attachment + 1u; 486 m_blend_state.pAttachments = m_blend_attachments.data(); 487 m_ci.pColorBlendState = &m_blend_state; 488 } 489 } 490 491 void Vulkan::GraphicsPipelineBuilder::SetColorWriteMask(u32 attachment, VkColorComponentFlags write_mask) 492 { 493 DebugAssert(attachment < MAX_ATTACHMENTS); 494 495 VkPipelineColorBlendAttachmentState& bs = m_blend_attachments[attachment]; 496 bs.colorWriteMask = write_mask; 497 } 498 499 void Vulkan::GraphicsPipelineBuilder::AddBlendFlags(u32 flags) 500 { 501 m_blend_state.flags |= flags; 502 } 503 504 void Vulkan::GraphicsPipelineBuilder::ClearBlendAttachments() 505 { 506 m_blend_attachments = {}; 507 m_blend_state.attachmentCount = 0; 508 } 509 510 void Vulkan::GraphicsPipelineBuilder::SetNoBlendingState() 511 { 512 ClearBlendAttachments(); 513 SetBlendAttachment(0, false, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE, 514 VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, 515 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | 516 VK_COLOR_COMPONENT_A_BIT); 517 } 518 519 void Vulkan::GraphicsPipelineBuilder::AddDynamicState(VkDynamicState state) 520 { 521 DebugAssert(m_dynamic_state.dynamicStateCount < MAX_DYNAMIC_STATE); 522 523 m_dynamic_state_values[m_dynamic_state.dynamicStateCount] = state; 524 m_dynamic_state.dynamicStateCount++; 525 m_dynamic_state.pDynamicStates = m_dynamic_state_values.data(); 526 m_ci.pDynamicState = &m_dynamic_state; 527 } 528 529 void Vulkan::GraphicsPipelineBuilder::SetDynamicViewportAndScissorState() 530 { 531 AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT); 532 AddDynamicState(VK_DYNAMIC_STATE_SCISSOR); 533 } 534 535 void Vulkan::GraphicsPipelineBuilder::SetViewport(float x, float y, float width, float height, float min_depth, 536 float max_depth) 537 { 538 m_viewport.x = x; 539 m_viewport.y = y; 540 m_viewport.width = width; 541 m_viewport.height = height; 542 m_viewport.minDepth = min_depth; 543 m_viewport.maxDepth = max_depth; 544 545 m_viewport_state.pViewports = &m_viewport; 546 m_viewport_state.viewportCount = 1u; 547 m_ci.pViewportState = &m_viewport_state; 548 } 549 550 void Vulkan::GraphicsPipelineBuilder::SetScissorRect(s32 x, s32 y, u32 width, u32 height) 551 { 552 m_scissor.offset.x = x; 553 m_scissor.offset.y = y; 554 m_scissor.extent.width = width; 555 m_scissor.extent.height = height; 556 557 m_viewport_state.pScissors = &m_scissor; 558 m_viewport_state.scissorCount = 1u; 559 m_ci.pViewportState = &m_viewport_state; 560 } 561 562 void Vulkan::GraphicsPipelineBuilder::SetPipelineLayout(VkPipelineLayout layout) 563 { 564 m_ci.layout = layout; 565 } 566 567 void Vulkan::GraphicsPipelineBuilder::SetRenderPass(VkRenderPass render_pass, u32 subpass) 568 { 569 m_ci.renderPass = render_pass; 570 m_ci.subpass = subpass; 571 } 572 573 void Vulkan::GraphicsPipelineBuilder::SetProvokingVertex(VkProvokingVertexModeEXT mode) 574 { 575 AddPointerToChain(&m_rasterization_state, &m_provoking_vertex); 576 577 m_provoking_vertex.provokingVertexMode = mode; 578 } 579 580 void Vulkan::GraphicsPipelineBuilder::SetDynamicRendering() 581 { 582 AddPointerToChain(&m_ci, &m_rendering); 583 } 584 585 void Vulkan::GraphicsPipelineBuilder::AddDynamicRenderingColorAttachment(VkFormat format) 586 { 587 SetDynamicRendering(); 588 589 DebugAssert(m_rendering.colorAttachmentCount < MAX_ATTACHMENTS); 590 m_rendering_color_formats[m_rendering.colorAttachmentCount++] = format; 591 592 m_rendering.pColorAttachmentFormats = m_rendering_color_formats.data(); 593 } 594 595 void Vulkan::GraphicsPipelineBuilder::SetDynamicRenderingDepthAttachment(VkFormat depth_format, VkFormat stencil_format) 596 { 597 SetDynamicRendering(); 598 599 m_rendering.depthAttachmentFormat = depth_format; 600 m_rendering.stencilAttachmentFormat = stencil_format; 601 } 602 603 void Vulkan::GraphicsPipelineBuilder::AddDynamicRenderingInputAttachment(u32 color_attachment_index) 604 { 605 AddPointerToChain(&m_ci, &m_rendering_input_attachment_locations); 606 607 DebugAssert(color_attachment_index < m_rendering.colorAttachmentCount); 608 DebugAssert(m_rendering_input_attachment_locations.colorAttachmentCount < MAX_INPUT_ATTACHMENTS); 609 610 m_rendering_input_attachment_locations.pColorAttachmentLocations = m_rendering_input_attachment_indices.data(); 611 m_rendering_input_attachment_indices[m_rendering_input_attachment_locations.colorAttachmentCount] = 612 color_attachment_index; 613 m_rendering_input_attachment_locations.colorAttachmentCount++; 614 } 615 616 Vulkan::ComputePipelineBuilder::ComputePipelineBuilder() 617 { 618 Clear(); 619 } 620 621 void Vulkan::ComputePipelineBuilder::Clear() 622 { 623 m_ci = {}; 624 m_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; 625 m_si = {}; 626 m_smap_entries = {}; 627 m_smap_constants = {}; 628 } 629 630 VkPipeline Vulkan::ComputePipelineBuilder::Create(VkDevice device, VkPipelineCache pipeline_cache /*= VK_NULL_HANDLE*/, 631 bool clear /*= true*/) 632 { 633 VkPipeline pipeline; 634 VkResult res = vkCreateComputePipelines(device, pipeline_cache, 1, &m_ci, nullptr, &pipeline); 635 if (res != VK_SUCCESS) 636 { 637 LOG_VULKAN_ERROR(res, "vkCreateComputePipelines() failed: "); 638 return VK_NULL_HANDLE; 639 } 640 641 if (clear) 642 Clear(); 643 644 return pipeline; 645 } 646 647 void Vulkan::ComputePipelineBuilder::SetShader(VkShaderModule module, const char* entry_point) 648 { 649 m_ci.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 650 m_ci.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; 651 m_ci.stage.module = module; 652 m_ci.stage.pName = entry_point; 653 } 654 655 void Vulkan::ComputePipelineBuilder::SetPipelineLayout(VkPipelineLayout layout) 656 { 657 m_ci.layout = layout; 658 } 659 660 void Vulkan::ComputePipelineBuilder::SetSpecializationBool(u32 index, bool value) 661 { 662 const u32 u32_value = static_cast<u32>(value); 663 SetSpecializationValue(index, u32_value); 664 } 665 666 void Vulkan::ComputePipelineBuilder::SetSpecializationValue(u32 index, u32 value) 667 { 668 if (m_si.mapEntryCount == 0) 669 { 670 m_si.pMapEntries = m_smap_entries.data(); 671 m_si.pData = m_smap_constants.data(); 672 m_ci.stage.pSpecializationInfo = &m_si; 673 } 674 675 m_smap_entries[m_si.mapEntryCount++] = {index, index * SPECIALIZATION_CONSTANT_SIZE, SPECIALIZATION_CONSTANT_SIZE}; 676 m_si.dataSize += SPECIALIZATION_CONSTANT_SIZE; 677 } 678 679 Vulkan::SamplerBuilder::SamplerBuilder() 680 { 681 Clear(); 682 } 683 684 void Vulkan::SamplerBuilder::Clear() 685 { 686 m_ci = {}; 687 m_ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 688 } 689 690 VkSampler Vulkan::SamplerBuilder::Create(VkDevice device, bool clear /* = true */) 691 { 692 VkSampler sampler; 693 VkResult res = vkCreateSampler(device, &m_ci, nullptr, &sampler); 694 if (res != VK_SUCCESS) 695 { 696 LOG_VULKAN_ERROR(res, "vkCreateSampler() failed: "); 697 return VK_NULL_HANDLE; 698 } 699 700 return sampler; 701 } 702 703 void Vulkan::SamplerBuilder::SetFilter(VkFilter mag_filter, VkFilter min_filter, VkSamplerMipmapMode mip_filter) 704 { 705 m_ci.magFilter = mag_filter; 706 m_ci.minFilter = min_filter; 707 m_ci.mipmapMode = mip_filter; 708 } 709 710 void Vulkan::SamplerBuilder::SetAddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w) 711 { 712 m_ci.addressModeU = u; 713 m_ci.addressModeV = v; 714 m_ci.addressModeW = w; 715 } 716 717 void Vulkan::SamplerBuilder::SetPointSampler( 718 VkSamplerAddressMode address_mode /* = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER */) 719 { 720 Clear(); 721 SetFilter(VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST); 722 SetAddressMode(address_mode, address_mode, address_mode); 723 } 724 725 void Vulkan::SamplerBuilder::SetLinearSampler( 726 bool mipmaps, VkSamplerAddressMode address_mode /* = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER */) 727 { 728 Clear(); 729 SetFilter(VK_FILTER_LINEAR, VK_FILTER_LINEAR, 730 mipmaps ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST); 731 SetAddressMode(address_mode, address_mode, address_mode); 732 733 if (mipmaps) 734 { 735 m_ci.minLod = std::numeric_limits<float>::min(); 736 m_ci.maxLod = std::numeric_limits<float>::max(); 737 } 738 } 739 740 Vulkan::DescriptorSetUpdateBuilder::DescriptorSetUpdateBuilder() 741 { 742 Clear(); 743 } 744 745 void Vulkan::DescriptorSetUpdateBuilder::Clear() 746 { 747 m_writes = {}; 748 m_num_writes = 0; 749 } 750 751 void Vulkan::DescriptorSetUpdateBuilder::Update(VkDevice device, bool clear /*= true*/) 752 { 753 DebugAssert(m_num_writes > 0); 754 755 vkUpdateDescriptorSets(device, m_num_writes, (m_num_writes > 0) ? m_writes.data() : nullptr, 0, nullptr); 756 757 if (clear) 758 Clear(); 759 } 760 761 void Vulkan::DescriptorSetUpdateBuilder::PushUpdate(VkCommandBuffer cmdbuf, VkPipelineBindPoint bind_point, 762 VkPipelineLayout layout, u32 set, bool clear /*= true*/) 763 { 764 DebugAssert(m_num_writes > 0); 765 766 vkCmdPushDescriptorSetKHR(cmdbuf, bind_point, layout, set, m_num_writes, m_writes.data()); 767 768 if (clear) 769 Clear(); 770 } 771 772 void Vulkan::DescriptorSetUpdateBuilder::AddImageDescriptorWrite( 773 VkDescriptorSet set, u32 binding, VkImageView view, 774 VkImageLayout layout /*= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL*/) 775 { 776 DebugAssert(m_num_writes < MAX_WRITES && m_num_image_infos < MAX_IMAGE_INFOS); 777 778 VkDescriptorImageInfo& ii = m_image_infos[m_num_image_infos++]; 779 ii.imageView = view; 780 ii.imageLayout = layout; 781 ii.sampler = VK_NULL_HANDLE; 782 783 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 784 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 785 dw.dstSet = set; 786 dw.dstBinding = binding; 787 dw.descriptorCount = 1; 788 dw.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; 789 dw.pImageInfo = ⅈ 790 } 791 792 void Vulkan::DescriptorSetUpdateBuilder::AddSamplerDescriptorWrite(VkDescriptorSet set, u32 binding, VkSampler sampler) 793 { 794 DebugAssert(m_num_writes < MAX_WRITES && m_num_image_infos < MAX_IMAGE_INFOS); 795 796 VkDescriptorImageInfo& ii = m_image_infos[m_num_image_infos++]; 797 ii.imageView = VK_NULL_HANDLE; 798 ii.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; 799 ii.sampler = sampler; 800 801 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 802 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 803 dw.dstSet = set; 804 dw.dstBinding = binding; 805 dw.descriptorCount = 1; 806 dw.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; 807 dw.pImageInfo = ⅈ 808 } 809 810 void Vulkan::DescriptorSetUpdateBuilder::AddSamplerDescriptorWrites(VkDescriptorSet set, u32 binding, 811 const VkSampler* samplers, u32 num_samplers) 812 { 813 DebugAssert(m_num_writes < MAX_WRITES && (m_num_image_infos + num_samplers) < MAX_IMAGE_INFOS); 814 815 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 816 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 817 dw.dstSet = set; 818 dw.dstBinding = binding; 819 dw.descriptorCount = num_samplers; 820 dw.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; 821 dw.pImageInfo = &m_image_infos[m_num_image_infos]; 822 823 for (u32 i = 0; i < num_samplers; i++) 824 { 825 VkDescriptorImageInfo& ii = m_image_infos[m_num_image_infos++]; 826 ii.imageView = VK_NULL_HANDLE; 827 ii.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 828 ii.sampler = samplers[i]; 829 } 830 } 831 832 void Vulkan::DescriptorSetUpdateBuilder::AddCombinedImageSamplerDescriptorWrite( 833 VkDescriptorSet set, u32 binding, VkImageView view, VkSampler sampler, 834 VkImageLayout layout /*= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL*/) 835 { 836 DebugAssert(m_num_writes < MAX_WRITES && m_num_image_infos < MAX_IMAGE_INFOS); 837 838 VkDescriptorImageInfo& ii = m_image_infos[m_num_image_infos++]; 839 ii.imageView = view; 840 ii.imageLayout = layout; 841 ii.sampler = sampler; 842 843 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 844 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 845 dw.dstSet = set; 846 dw.dstBinding = binding; 847 dw.descriptorCount = 1; 848 dw.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 849 dw.pImageInfo = ⅈ 850 } 851 852 void Vulkan::DescriptorSetUpdateBuilder::AddCombinedImageSamplerDescriptorWrites( 853 VkDescriptorSet set, u32 binding, const VkImageView* views, const VkSampler* samplers, u32 num_views, 854 VkImageLayout layout /* = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL */) 855 { 856 DebugAssert(m_num_writes < MAX_WRITES && (m_num_image_infos + num_views) < MAX_IMAGE_INFOS); 857 858 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 859 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 860 dw.dstSet = set; 861 dw.dstBinding = binding; 862 dw.descriptorCount = num_views; 863 dw.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 864 dw.pImageInfo = &m_image_infos[m_num_image_infos]; 865 866 for (u32 i = 0; i < num_views; i++) 867 { 868 VkDescriptorImageInfo& ii = m_image_infos[m_num_image_infos++]; 869 ii.imageView = views[i]; 870 ii.sampler = samplers[i]; 871 ii.imageLayout = layout; 872 } 873 } 874 875 void Vulkan::DescriptorSetUpdateBuilder::AddBufferDescriptorWrite(VkDescriptorSet set, u32 binding, 876 VkDescriptorType dtype, VkBuffer buffer, u32 offset, 877 u32 size) 878 { 879 DebugAssert(m_num_writes < MAX_WRITES && m_num_buffer_infos < MAX_BUFFER_INFOS); 880 881 VkDescriptorBufferInfo& bi = m_buffer_infos[m_num_buffer_infos++]; 882 bi.buffer = buffer; 883 bi.offset = offset; 884 bi.range = size; 885 886 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 887 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 888 dw.dstSet = set; 889 dw.dstBinding = binding; 890 dw.descriptorCount = 1; 891 dw.descriptorType = dtype; 892 dw.pBufferInfo = &bi; 893 } 894 895 void Vulkan::DescriptorSetUpdateBuilder::AddBufferViewDescriptorWrite(VkDescriptorSet set, u32 binding, 896 VkDescriptorType dtype, VkBufferView view) 897 { 898 DebugAssert(m_num_writes < MAX_WRITES && m_num_views < MAX_VIEWS); 899 900 VkBufferView& bi = m_views[m_num_views++]; 901 bi = view; 902 903 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 904 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 905 dw.dstSet = set; 906 dw.dstBinding = binding; 907 dw.descriptorCount = 1; 908 dw.descriptorType = dtype; 909 dw.pTexelBufferView = &bi; 910 } 911 912 void Vulkan::DescriptorSetUpdateBuilder::AddInputAttachmentDescriptorWrite( 913 VkDescriptorSet set, u32 binding, VkImageView view, VkImageLayout layout /*= VK_IMAGE_LAYOUT_GENERAL*/) 914 { 915 DebugAssert(m_num_writes < MAX_WRITES && m_num_image_infos < MAX_IMAGE_INFOS); 916 917 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 918 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 919 dw.dstSet = set; 920 dw.dstBinding = binding; 921 dw.descriptorCount = 1; 922 dw.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 923 dw.pImageInfo = &m_image_infos[m_num_image_infos]; 924 925 VkDescriptorImageInfo& ii = m_image_infos[m_num_image_infos++]; 926 ii.imageView = view; 927 ii.imageLayout = layout; 928 ii.sampler = VK_NULL_HANDLE; 929 } 930 931 void Vulkan::DescriptorSetUpdateBuilder::AddStorageImageDescriptorWrite( 932 VkDescriptorSet set, u32 binding, VkImageView view, VkImageLayout layout /*= VK_IMAGE_LAYOUT_GENERAL*/) 933 { 934 DebugAssert(m_num_writes < MAX_WRITES && m_num_image_infos < MAX_IMAGE_INFOS); 935 936 VkWriteDescriptorSet& dw = m_writes[m_num_writes++]; 937 dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 938 dw.dstSet = set; 939 dw.dstBinding = binding; 940 dw.descriptorCount = 1; 941 dw.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 942 dw.pImageInfo = &m_image_infos[m_num_image_infos]; 943 944 VkDescriptorImageInfo& ii = m_image_infos[m_num_image_infos++]; 945 ii.imageView = view; 946 ii.imageLayout = layout; 947 ii.sampler = VK_NULL_HANDLE; 948 } 949 950 Vulkan::FramebufferBuilder::FramebufferBuilder() 951 { 952 Clear(); 953 } 954 955 void Vulkan::FramebufferBuilder::Clear() 956 { 957 m_ci = {}; 958 m_ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 959 m_images = {}; 960 } 961 962 VkFramebuffer Vulkan::FramebufferBuilder::Create(VkDevice device, bool clear /*= true*/) 963 { 964 VkFramebuffer fb; 965 VkResult res = vkCreateFramebuffer(device, &m_ci, nullptr, &fb); 966 if (res != VK_SUCCESS) 967 { 968 LOG_VULKAN_ERROR(res, "vkCreateFramebuffer() failed: "); 969 return VK_NULL_HANDLE; 970 } 971 972 if (clear) 973 Clear(); 974 975 return fb; 976 } 977 978 void Vulkan::FramebufferBuilder::AddAttachment(VkImageView image) 979 { 980 DebugAssert(m_ci.attachmentCount < MAX_ATTACHMENTS); 981 982 m_images[m_ci.attachmentCount] = image; 983 984 m_ci.attachmentCount++; 985 m_ci.pAttachments = m_images.data(); 986 } 987 988 void Vulkan::FramebufferBuilder::SetSize(u32 width, u32 height, u32 layers) 989 { 990 m_ci.width = width; 991 m_ci.height = height; 992 m_ci.layers = layers; 993 } 994 995 void Vulkan::FramebufferBuilder::SetRenderPass(VkRenderPass render_pass) 996 { 997 m_ci.renderPass = render_pass; 998 } 999 1000 Vulkan::RenderPassBuilder::RenderPassBuilder() 1001 { 1002 Clear(); 1003 } 1004 1005 void Vulkan::RenderPassBuilder::Clear() 1006 { 1007 m_ci = {}; 1008 m_ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 1009 m_attachments = {}; 1010 m_attachment_references = {}; 1011 m_num_attachment_references = 0; 1012 m_subpasses = {}; 1013 } 1014 1015 VkRenderPass Vulkan::RenderPassBuilder::Create(VkDevice device, bool clear /*= true*/) 1016 { 1017 VkRenderPass rp; 1018 VkResult res = vkCreateRenderPass(device, &m_ci, nullptr, &rp); 1019 if (res != VK_SUCCESS) 1020 { 1021 LOG_VULKAN_ERROR(res, "vkCreateRenderPass() failed: "); 1022 return VK_NULL_HANDLE; 1023 } 1024 1025 return rp; 1026 } 1027 1028 u32 Vulkan::RenderPassBuilder::AddAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load_op, 1029 VkAttachmentStoreOp store_op, VkImageLayout initial_layout, 1030 VkImageLayout final_layout) 1031 { 1032 DebugAssert(m_ci.attachmentCount < MAX_ATTACHMENTS); 1033 1034 const u32 index = m_ci.attachmentCount; 1035 VkAttachmentDescription& ad = m_attachments[index]; 1036 ad.format = format; 1037 ad.samples = samples; 1038 ad.loadOp = load_op; 1039 ad.storeOp = store_op; 1040 ad.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1041 ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1042 ad.initialLayout = initial_layout; 1043 ad.finalLayout = final_layout; 1044 1045 m_ci.attachmentCount++; 1046 m_ci.pAttachments = m_attachments.data(); 1047 1048 return index; 1049 } 1050 1051 u32 Vulkan::RenderPassBuilder::AddSubpass() 1052 { 1053 DebugAssert(m_ci.subpassCount < MAX_SUBPASSES); 1054 1055 const u32 index = m_ci.subpassCount; 1056 VkSubpassDescription& sp = m_subpasses[index]; 1057 sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 1058 1059 m_ci.subpassCount++; 1060 m_ci.pSubpasses = m_subpasses.data(); 1061 1062 return index; 1063 } 1064 1065 void Vulkan::RenderPassBuilder::AddSubpassColorAttachment(u32 subpass, u32 attachment, VkImageLayout layout) 1066 { 1067 DebugAssert(subpass < m_ci.subpassCount && m_num_attachment_references < MAX_ATTACHMENT_REFERENCES); 1068 1069 VkAttachmentReference& ar = m_attachment_references[m_num_attachment_references++]; 1070 ar.attachment = attachment; 1071 ar.layout = layout; 1072 1073 VkSubpassDescription& sp = m_subpasses[subpass]; 1074 if (sp.colorAttachmentCount == 0) 1075 sp.pColorAttachments = &ar; 1076 sp.colorAttachmentCount++; 1077 } 1078 1079 void Vulkan::RenderPassBuilder::AddSubpassDepthAttachment(u32 subpass, u32 attachment, VkImageLayout layout) 1080 { 1081 DebugAssert(subpass < m_ci.subpassCount && m_num_attachment_references < MAX_ATTACHMENT_REFERENCES); 1082 1083 VkAttachmentReference& ar = m_attachment_references[m_num_attachment_references++]; 1084 ar.attachment = attachment; 1085 ar.layout = layout; 1086 1087 VkSubpassDescription& sp = m_subpasses[subpass]; 1088 sp.pDepthStencilAttachment = &ar; 1089 } 1090 1091 Vulkan::BufferViewBuilder::BufferViewBuilder() 1092 { 1093 Clear(); 1094 } 1095 1096 void Vulkan::BufferViewBuilder::Clear() 1097 { 1098 m_ci = {}; 1099 m_ci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; 1100 } 1101 1102 VkBufferView Vulkan::BufferViewBuilder::Create(VkDevice device, bool clear /*= true*/) 1103 { 1104 VkBufferView bv; 1105 VkResult res = vkCreateBufferView(device, &m_ci, nullptr, &bv); 1106 if (res != VK_SUCCESS) 1107 { 1108 LOG_VULKAN_ERROR(res, "vkCreateBufferView() failed: "); 1109 return VK_NULL_HANDLE; 1110 } 1111 1112 return bv; 1113 } 1114 1115 void Vulkan::BufferViewBuilder::Set(VkBuffer buffer, VkFormat format, u32 offset, u32 size) 1116 { 1117 m_ci.buffer = buffer; 1118 m_ci.format = format; 1119 m_ci.offset = offset; 1120 m_ci.range = size; 1121 }